/** * Reads data starting from {@code offsetToStartRead} of {@code segment} and matches it with * {@code original}. * * @param segment the {@link LogSegment} to read from. * @param offsetToStartRead the offset in {@code segment} to start reading from. * @param original the byte array to compare against. * @throws IOException */ private void readAndEnsureMatch(LogSegment segment, long offsetToStartRead, byte[] original) throws IOException { ByteBuffer readBuf = ByteBuffer.wrap(new byte[original.length]); segment.readInto(readBuf, offsetToStartRead); assertArrayEquals("Data read does not match data written", original, readBuf.array()); }
/** * Tests {@link LogSegment#readInto(ByteBuffer, long)} for various cases. * * @throws IOException */ @Test public void readTest() throws IOException { Random random = new Random(); String segmentName = "log_current"; LogSegment segment = getSegment(segmentName, STANDARD_SEGMENT_SIZE, true); try { long writeStartOffset = segment.getStartOffset(); byte[] data = appendRandomData(segment, 2 * STANDARD_SEGMENT_SIZE / 3); readAndEnsureMatch(segment, writeStartOffset, data); int readCount = 10; for (int i = 0; i < readCount; i++) { int position = random.nextInt(data.length); int size = random.nextInt(data.length - position); readAndEnsureMatch( segment, writeStartOffset + position, Arrays.copyOfRange(data, position, position + size)); } // error scenarios ByteBuffer readBuf = ByteBuffer.wrap(new byte[data.length]); // data cannot be read at invalid offsets. long[] invalidOffsets = { writeStartOffset - 1, segment.getEndOffset(), segment.getEndOffset() + 1 }; ByteBuffer buffer = ByteBuffer.wrap(TestUtils.getRandomBytes(1)); for (long invalidOffset : invalidOffsets) { try { segment.readInto(readBuf, invalidOffset); fail("Should have failed to read because position provided is invalid"); } catch (IndexOutOfBoundsException e) { assertEquals("Position of buffer has changed", 0, buffer.position()); } } // position + buffer.remaining() > endOffset. long readOverFlowCount = metrics.overflowReadError.getCount(); try { segment.readInto(readBuf, writeStartOffset + 1); fail("Should have failed to read because position + buffer.remaining() > endOffset"); } catch (IndexOutOfBoundsException e) { assertEquals( "Read overflow should have been reported", readOverFlowCount + 1, metrics.overflowReadError.getCount()); assertEquals("Position of buffer has changed", 0, readBuf.position()); } segment.close(); // read after close buffer = ByteBuffer.allocate(1); try { segment.readInto(buffer, writeStartOffset); fail("Should have failed to read because segment is closed"); } catch (ClosedChannelException e) { assertEquals("Position of buffer has changed", 0, buffer.position()); } } finally { closeSegmentAndDeleteFile(segment); } }