### Question:
IbftProcessor implements Runnable { public void stop() { shutdown = true; } IbftProcessor(
      final IbftEventQueue incomingQueue, final EventMultiplexer eventMultiplexer); void stop(); void awaitStop(); @Override void run();  }### Answer:
@Test public void handlesStopGracefully() throws InterruptedException { final IbftEventQueue mockQueue = mock(IbftEventQueue.class); Mockito.when(mockQueue.poll(anyLong(), any())).thenReturn(null); final IbftProcessor processor = new IbftProcessor(mockQueue, mockeEventMultiplexer); final ExecutorService processorExecutor = Executors.newSingleThreadExecutor(); final Future<?> processorFuture = processorExecutor.submit(processor); verify(mockQueue, timeout(3000).atLeastOnce()).poll(anyLong(), any()); processor.stop(); processorExecutor.shutdown(); final boolean executorCompleted = processorExecutor.awaitTermination(2000, TimeUnit.MILLISECONDS); assertThat(executorCompleted).isTrue(); assertThat(processorFuture.isDone()).isTrue(); }
@Test public void cleanupExecutorsAfterShutdownNow() throws InterruptedException { final IbftProcessor processor = new IbftProcessor(new IbftEventQueue(1000), mockeEventMultiplexer); final ExecutorService processorExecutor = Executors.newSingleThreadExecutor(); final Future<?> processorFuture = processorExecutor.submit(processor); processor.stop(); processorExecutor.shutdownNow(); final boolean executorCompleted = processorExecutor.awaitTermination(2000, TimeUnit.MILLISECONDS); assertThat(executorCompleted).isTrue(); assertThat(processorFuture.isDone()).isTrue(); }
@Test public void handlesQueueInterruptGracefully() throws InterruptedException { final IbftEventQueue mockQueue = mock(IbftEventQueue.class); Mockito.when(mockQueue.poll(anyLong(), any())).thenThrow(new InterruptedException()); final IbftProcessor processor = new IbftProcessor(mockQueue, mockeEventMultiplexer); final ExecutorService processorExecutor = Executors.newSingleThreadExecutor(); final Future<?> processorFuture = processorExecutor.submit(processor); verify(mockQueue, timeout(3000).atLeastOnce()).poll(anyLong(), any()); processorExecutor.shutdown(); assertThat(processorFuture.isDone()).isFalse(); processor.stop(); final boolean executorCompleted = processorExecutor.awaitTermination(200, TimeUnit.MILLISECONDS); assertThat(executorCompleted).isTrue(); assertThat(processorFuture.isDone()).isTrue(); }
@Test public void drainEventsIntoStateMachine() throws InterruptedException { final IbftEventQueue queue = new IbftEventQueue(1000); final IbftProcessor processor = new IbftProcessor(queue, mockeEventMultiplexer); final ExecutorService processorExecutor = Executors.newSingleThreadExecutor(); processorExecutor.execute(processor); final RoundExpiry roundExpiryEvent = new RoundExpiry(new ConsensusRoundIdentifier(1, 1)); queue.add(roundExpiryEvent); queue.add(roundExpiryEvent); await().atMost(3000, TimeUnit.MILLISECONDS).until(queue::isEmpty); processor.stop(); processorExecutor.shutdown(); verify(mockeEventMultiplexer, times(2)).handleIbftEvent(eq(roundExpiryEvent)); }