### Question:
SubstreamInputStream extends InputStream { @Override public int read() { if (lengthRemaining <= 0) return -1; int byteRead = outerInputStream.read(); if (byteRead == -1) throw new IOException( "SubstreamInputStream outer stream returned end of stream prematurely; there are {} bytes left to read", lengthRemaining); lengthRemaining -= 1; return byteRead; } SubstreamInputStream(InputStream inputStream, int length); @Override void close(); @Override int read(); @Override int read(byte[] buffer, int offset, int length);  }### Answer:
@Test public void testReadByte() { byte[] testData = new byte[100]; for (int i = 0; i < testData.length; i++) { testData[i] = (byte) i; } byte[] buffer = new byte[4]; int byteRead; ByteArrayInputStream outerStream = new ByteArrayInputStream(testData); SubstreamInputStream substreamInputStream = new SubstreamInputStream(outerStream, 2); byteRead = substreamInputStream.read(); assertEquals(0, byteRead); byteRead = substreamInputStream.read(); assertEquals(1, byteRead); byteRead = substreamInputStream.read(); assertEquals(-1, byteRead); outerStream = new ByteArrayInputStream(testData); substreamInputStream = new SubstreamInputStream(outerStream, 200); for (int i = 0; i < 100; i++) { byteRead = substreamInputStream.read(); assertEquals(i, byteRead); } boolean exceptionThrown = false; try { substreamInputStream.read(); } catch (IOException e) { exceptionThrown = true; } assertTrue(exceptionThrown); }
@Test public void testRead() { byte[] testData = new byte[100]; for (int i = 0; i < testData.length; i++) { testData[i] = (byte) i; } byte[] buffer = new byte[4]; int amountRead; ByteArrayInputStream outerStream = new ByteArrayInputStream(testData); SubstreamInputStream substreamInputStream = new SubstreamInputStream(outerStream, 4); amountRead = substreamInputStream.read(buffer); assertEquals(4, amountRead); assertEquals(3, buffer[3]); amountRead = substreamInputStream.read(buffer); assertEquals(-1, amountRead); amountRead = substreamInputStream.read(buffer); assertEquals(-1, amountRead); amountRead = substreamInputStream.read(buffer, 2, 0); assertEquals(0, amountRead); outerStream = new ByteArrayInputStream(testData); substreamInputStream = new SubstreamInputStream(outerStream, 4); buffer = new byte[10]; amountRead = substreamInputStream.read(buffer); assertEquals(4, amountRead); assertEquals(3, buffer[3]); amountRead = substreamInputStream.read(buffer); assertEquals(-1, amountRead); outerStream = new ByteArrayInputStream(testData); substreamInputStream = new SubstreamInputStream(outerStream, 200); buffer = new byte[150]; amountRead = substreamInputStream.read(buffer); assertEquals(100, amountRead); boolean exceptionThrown = false; try { substreamInputStream.read(buffer); } catch (IOException e) { exceptionThrown = true; } assertTrue(exceptionThrown); }