@Test public void testPartialRecord() throws IOException { // build a file with 2 and a half records File file = Files.createTempFile("foo-", ".data").toFile(); DataOutputStream out = new DataOutputStream(new FileOutputStream(file)); byte[] bytes = writePartialFile(out); // now verify we read 2 reads cleanly but hold off on the third ProtoSpout.MessageParserFactory factory = new ProtoSpout.MessageParserFactory( new ProtoSpout.TupleParser() { Splitter onSpace = Splitter.on(" "); @Override public List<Object> parse(ByteString buffer) { return Lists.<Object>newArrayList(onSpace.split(buffer.toStringUtf8())); } @Override public Fields getOutputFields() { throw new UnsupportedOperationException("Default operation"); } }); StreamParser parser = factory.createParser(new FileInputStream(file)); assertTrue(file.length() > 30); assertEquals(0, parser.currentOffset()); List<Object> t = parser.nextRecord(); assertEquals(2, t.size()); assertEquals("test", t.get(0)); assertEquals("1", t.get(1)); t = parser.nextRecord(); assertEquals(2, t.size()); assertEquals("test", t.get(0)); assertEquals("2", t.get(1)); // time critical section starts here ... delay > 50ms can cause failure // first read doesn't see a full record and thus returns null t = parser.nextRecord(); assertNull(t); // write the remainder now out.write(bytes, 6, bytes.length - 6); // so that the repeated read succeeds t = parser.nextRecord(); // end of time critical section assertEquals(2, t.size()); assertEquals("test", t.get(0)); assertEquals("3", t.get(1)); assertNull(parser.nextRecord()); out.close(); }