public void testCursorTruncate() throws IOException, InterruptedException {
// normal implementation uses synchronous queue, but we use array blocking
// queue for single threaded testing
BlockingQueue<Event> q = new ArrayBlockingQueue<Event>(10);
File f = createDataFile(5);
Cursor c = new Cursor(q, f);
assertTrue(c.tailBody()); // open file the file
assertEquals(0, c.lastChannelPos);
assertTrue(null != c.in);
assertTrue(c.tailBody()); // finish reading the file
assertTrue(0 != c.lastChannelSize);
assertTrue(null != c.in);
assertFalse(c.tailBody()); // attempt to open file again.
assertEquals(5, q.size()); // should be 5 in queue.
// truncate the file -- there will be 1 full event and one unproperly closed
// event.
RandomAccessFile raf = new RandomAccessFile(f, "rw");
raf.setLength(10);
raf.close();
// TODO (jon): When a file gets truncated, because we don't have an
// inode we don't know if this is a new file or a truncated version of the
// original file. This is not a fundamental flaw -- safe assumption here is
// that it is a new file and according to our semantics, we are just
// duplicating information. NOTE: This is another place where this tail
// differs from the semantics of gnu-tail.
assertTrue(c.tailBody()); // reset changed file
assertEquals(0, c.lastChannelPos);
assertEquals(null, c.in);
assertTrue(c.tailBody()); // re-opens length changed file
assertTrue(0 != c.lastChannelSize);
assertTrue(null != c.in);
assertTrue(c.tailBody()); // finish reading the file
assertTrue(0 != c.lastChannelSize);
assertTrue(null != c.in);
assertFalse(c.tailBody()); // attempt to open file again.
assertEquals(6, q.size()); // should be 5 in queue.
c.flush();
assertTrue(c.tailBody()); // attempt to open file again.
assertEquals(7, q.size()); // should be 5 in queue.
}