InputTimeoutDetector { public void processInput() { if (isSessionStarted()) { final long currentTimestamp = getCurrentTimestamp(); if (!isSpeechDetected()) { firstInputTimestamp = currentTimestamp; if (logger.isTraceEnabled()) { logger.trace("processInput [firstInputTimestamp=" + firstInputTimestamp + "]"); } executor.schedule(new MaxInputTimeoutDetector(), maxInputTimeout, TimeUnit.NANOSECONDS); } lastInputTimestamp = currentTimestamp; if (logger.isTraceEnabled()) { logger.trace("processInput [lastInputTimestamp=" + lastInputTimestamp + "]"); } executor.schedule(new NextInputTimeoutDetector(), nextInputTimeout, TimeUnit.NANOSECONDS); } else { logger.warn("processInput: Session is not started"); } } InputTimeoutDetector(final ListeningScheduledExecutorService executor); void startSession(final InputTimeoutListener listener, final long firstInputTimeout, final long maxInputTimeout, final long nextInputTimeout); void startWaitingForFirstInput(); void processInput(); long getIdleTimeInNanoseconds(); void stopSession(); boolean isSpeechDetected();  }
@Test public void testSpeechBeforeWaitingForFirstInput() throws InterruptedException { testee.processInput(); verify(executor, times(2)).schedule(any(Runnable.class), anyLong(), any(TimeUnit.class)); assertEquals(0, scheduledDetectorCounter.getFirstInputTimeoutDetectorCounter()); assertEquals(1, scheduledDetectorCounter.getNextInputTimeoutDetectorCounter()); assertEquals(1, scheduledDetectorCounter.getMaxInputTimeoutDetectorCounter()); }