Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c1823701 authored by Bjorn Bringert's avatar Bjorn Bringert
Browse files

Handle EOF correctly in MemoryFile input stream.

Before, the variants of MemoryFile.MemoryInputStream.read() would throw
IOException or  IndexOutOfBoundsException if EOF was encountered
before the requested number of bytes was read. This violates
the contract of InputStream.read().

This patch makes read() return the number of bytes available, if any.
If already at EOF, -1 is returned. The patch also adds new tests,
which checks cases where MemoryFile.MemoryInputStream.read()
should throw IndexOutOfBoundsException or return -1. several of these
tests failed with the old code and pass now.

This fixes http://b/issue?id=1881894
parent 963cd006
Loading
Loading
Loading
Loading
+10 −1
Original line number Original line Diff line number Diff line
@@ -353,13 +353,22 @@ public class MemoryFile
            }
            }
            int result = read(mSingleByte, 0, 1);
            int result = read(mSingleByte, 0, 1);
            if (result != 1) {
            if (result != 1) {
                throw new IOException("read() failed");
                return -1;
            }
            }
            return mSingleByte[0];
            return mSingleByte[0];
        }
        }


        @Override
        @Override
        public int read(byte buffer[], int offset, int count) throws IOException {
        public int read(byte buffer[], int offset, int count) throws IOException {
            if (offset < 0 || count < 0 || offset + count > buffer.length) {
                // readBytes() also does this check, but we need to do it before
                // changing count.
                throw new IndexOutOfBoundsException();
            }
            count = Math.min(count, available());
            if (count < 1) {
                return -1;
            }
            int result = readBytes(buffer, mOffset, offset, count);
            int result = readBytes(buffer, mOffset, offset, count);
            if (result > 0) {
            if (result > 0) {
                mOffset += result;
                mOffset += result;
+1 −2
Original line number Original line Diff line number Diff line
@@ -40,8 +40,7 @@ public class MemoryFileProviderTest extends AndroidTestCase {
        assertNotNull(in);
        assertNotNull(in);
        int count = in.read(buf);
        int count = in.read(buf);
        assertEquals(buf.length, count);
        assertEquals(buf.length, count);
        // TODO: MemoryFile throws IndexOutOfBoundsException for this, http://b/issue?id=1881894
        assertEquals(-1, in.read());
        //assertEquals(-1, in.read());
        in.close();
        in.close();
        assertTrue(Arrays.equals(MemoryFileProvider.TEST_BLOB, buf));
        assertTrue(Arrays.equals(MemoryFileProvider.TEST_BLOB, buf));
    }
    }
+69 −0
Original line number Original line Diff line number Diff line
@@ -97,6 +97,74 @@ public class MemoryFileTest extends AndroidTestCase {
        file.close();
        file.close();
    }
    }


    // Tests for the IndexOutOfBoundsException cases in read().

    private void readIndexOutOfBoundsException(int offset, int count, String msg)
            throws Exception {
        MemoryFile file = new MemoryFile("MemoryFileTest", testString.length);
        try {
            file.writeBytes(testString, 0, 0, testString.length);
            InputStream is = file.getInputStream();
            byte[] buffer = new byte[testString.length + 10];
            try {
                is.read(buffer, offset, count);
                fail(msg);
            } catch (IndexOutOfBoundsException ex) {
                // this is what should happen
            } finally {
                is.close();
            }
        } finally {
            file.close();
        }
    }

    @SmallTest
    public void testReadNegativeOffset() throws Exception {
        readIndexOutOfBoundsException(-1, 5,
                "read() with negative offset should throw IndexOutOfBoundsException");
    }

    @SmallTest
    public void testReadNegativeCount() throws Exception {
        readIndexOutOfBoundsException(5, -1,
                "read() with negative length should throw IndexOutOfBoundsException");
    }

    @SmallTest
    public void testReadOffsetOverflow() throws Exception {
        readIndexOutOfBoundsException(testString.length + 10, 5,
                "read() with offset outside buffer should throw IndexOutOfBoundsException");
    }

    @SmallTest
    public void testReadOffsetCountOverflow() throws Exception {
        readIndexOutOfBoundsException(testString.length, 11,
                "read() with offset + count outside buffer should throw IndexOutOfBoundsException");
    }

    // Test behavior of read() at end of file
    @SmallTest
    public void testReadEOF() throws Exception {
        MemoryFile file = new MemoryFile("MemoryFileTest", testString.length);
        try {
            file.writeBytes(testString, 0, 0, testString.length);
            InputStream is = file.getInputStream();
            try {
                byte[] buffer = new byte[testString.length + 10];
                // read() with count larger than data should succeed, and return # of bytes read
                assertEquals(testString.length, is.read(buffer));
                compareBuffers(testString, buffer, testString.length);
                // Read at EOF should return -1
                assertEquals(-1, is.read());
            } finally {
                is.close();
            }
        } finally {
            file.close();
        }
    }

    // Tests that close() is idempotent
    // Tests that close() is idempotent
    @SmallTest
    @SmallTest
    public void testCloseClose() throws Exception {
    public void testCloseClose() throws Exception {
@@ -194,6 +262,7 @@ public class MemoryFileTest extends AndroidTestCase {
        }
        }
    }
    }


    @SmallTest
    public void testFileDescriptor() throws Exception {
    public void testFileDescriptor() throws Exception {
        MemoryFile file = new MemoryFile("MemoryFileTest", 1000000);
        MemoryFile file = new MemoryFile("MemoryFileTest", 1000000);
        MemoryFile ref = new MemoryFile(file.getFileDescriptor(), file.length(), "r");
        MemoryFile ref = new MemoryFile(file.getFileDescriptor(), file.length(), "r");