Source:
public void testAckBeforeSyncWithJournalBufferedEntriesThreshold() throws Exception { File journalDir = tempDir.newFolder(); Bookie.checkDirectoryStructure(Bookie.getCurrentDirectory(journalDir)); final int journalBufferedEntriesThreshold = 10; final int numEntries = journalBufferedEntriesThreshold + 50; ServerConfiguration conf = TestBKConfiguration.newServerConfiguration(); conf.setJournalDirName(journalDir.getPath()) .setJournalBufferedEntriesThreshold(journalBufferedEntriesThreshold) .setZkServers(null); LedgerDirsManager ledgerDirsManager = mock(LedgerDirsManager.class); Journal journal = new Journal(journalDir, conf, ledgerDirsManager); Counter flushMaxOutstandingBytesCounter = new CounterImpl(); Whitebox.setInternalState(journal, "flushMaxOutstandingBytesCounter", flushMaxOutstandingBytesCounter); journal.start(); CountDownLatch latch = new CountDownLatch(numEntries); AtomicInteger countForceWriteCallsBeforeAck = new AtomicInteger(); replace(method(JournalChannel.class, "forceWrite")).with(new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { log.info("{} called with arguments ", method.getName(), Arrays.toString(args)); if (latch.getCount() == numEntries) { countForceWriteCallsBeforeAck.incrementAndGet(); } try { method.invoke(proxy, args); } catch (InvocationTargetException err) { throw err.getCause(); } return null; } }); while (countForceWriteCallsBeforeAck.get() == 0) { Thread.sleep(100); } long ledgerId = 1; for (long entryId = 0; entryId < numEntries; entryId++) { journal.logAddEntry(ledgerId, entryId, DATA, true , new WriteCallback() { @Override public void writeComplete(int rc, long ledgerId, long entryId, BookieSocketAddress addr, Object ctx) { latch.countDown(); } }, null); } assertTrue(latch.await(20, TimeUnit.SECONDS)); assertTrue(flushMaxOutstandingBytesCounter.get() > 1); journal.shutdown(); }

Target:
public void testAckBeforeSyncWithJournalBufferedEntriesThreshold() throws Exception { File journalDir = tempDir.newFolder(); Bookie.checkDirectoryStructure(Bookie.getCurrentDirectory(journalDir)); final int journalBufferedEntriesThreshold = 10; final int numEntries = journalBufferedEntriesThreshold + 50; ServerConfiguration conf = TestBKConfiguration.newServerConfiguration(); conf.setJournalDirName(journalDir.getPath()) .setJournalBufferedEntriesThreshold(journalBufferedEntriesThreshold) .setZkServers(null); JournalChannel jc = spy(new JournalChannel(journalDir, 1)); whenNew(JournalChannel.class).withAnyArguments().thenReturn(jc); LedgerDirsManager ledgerDirsManager = mock(LedgerDirsManager.class); Journal journal = new Journal(journalDir, conf, ledgerDirsManager); CountDownLatch forceWriteThreadSuspendedLatch = new CountDownLatch(1); enableForceWriteThreadSuspension(forceWriteThreadSuspendedLatch, journal); TestStatsProvider testStatsProvider = new TestStatsProvider(); Counter flushMaxOutstandingBytesCounter = testStatsProvider.getStatsLogger("test") .getCounter("flushMaxOutstandingBytesCounter"); Whitebox.setInternalState(journal, "flushMaxOutstandingBytesCounter", flushMaxOutstandingBytesCounter); journal.start(); LogMark lastLogMarkBeforeWrite = journal.getLastLogMark().markLog().getCurMark(); CountDownLatch latch = new CountDownLatch(numEntries); long ledgerId = 1; for (long entryId = 0; entryId < numEntries; entryId++) { journal.logAddEntry(ledgerId, entryId, DATA, true , new WriteCallback() { @Override public void writeComplete(int rc, long ledgerId, long entryId, BookieSocketAddress addr, Object ctx) { latch.countDown(); } }, null); } latch.await(20, TimeUnit.SECONDS); verify(jc, times(0)).forceWrite(true); verify(jc, times(0)).forceWrite(false); LastLogMark lastLogMarkAfterForceWrite = journal.getLastLogMark(); assertEquals(0, lastLogMarkAfterForceWrite.getCurMark().compare(lastLogMarkBeforeWrite)); forceWriteThreadSuspendedLatch.countDown(); assertTrue(flushMaxOutstandingBytesCounter.get() > 1); journal.shutdown(); }