ProcessHelper { static int runWithTimeout(long timeoutInSeconds, Process process) throws InterruptedException, IOException { Preconditions.checkArgument(timeoutInSeconds > 0, "negative timeout: %s", timeoutInSeconds); int exitCode; long startTimeNano = System.nanoTime(); while (true) { try { exitCode = process.exitValue(); closeStream(process); return exitCode; } catch (IllegalThreadStateException ex) { long running = System.nanoTime() - startTimeNano; if (running > TimeUnit.SECONDS.toNanos(timeoutInSeconds)) { break; } TimeUnit.NANOSECONDS.sleep(smartWait(running, startTimeNano, timeoutInSeconds)); } } process.destroy(); exitCode = 124; closeStream(process); return exitCode; } private  ProcessHelper();   }
@Test public void testIllegalTimeout() { try { int exitCode = ProcessHelper.runWithTimeout(-1, process); fail(); } catch (Exception e) { assertEquals("negative timeout: -1", e.getMessage()); } }
@Test public void testWithTimeout() { try { when(process.exitValue()).thenThrow(new IllegalThreadStateException()) .thenThrow(new IllegalThreadStateException()) .thenReturn(0); int exitCode = ProcessHelper.runWithTimeout(10, process); assertEquals(0, exitCode); verify(process, never()).waitFor(); verify(process, times(3)).exitValue(); verify(process, never()).destroy(); } catch (Exception e) { fail(); } }
@Test public void testTimeouted() { try { when(process.exitValue()).thenThrow(new IllegalThreadStateException()); int exitCode = ProcessHelper.runWithTimeout(2, process); assertEquals(124, exitCode); verify(process, never()).waitFor(); verify(process, times(1)).destroy(); } catch (Exception e) { fail(); } }