// Copyright © 2010, Esko Luontola <www.orfjackal.net> // This software is released under the Apache License 2.0. // The license text is at http://www.apache.org/licenses/LICENSE-2.0 package net.orfjackal.sbt.runner; import org.junit.*; import java.io.*; import java.util.concurrent.*; import static org.junit.Assert.*; public class ProcessRunnerTest { private ProcessRunner process; @Before public void newProcess() throws IOException { process = new ProcessRunner(new File("."), "java", "-version"); } @After public void killProcess() { if (process != null) { process.destroy(); } } @Test public void is_alive_until_it_is_destroyed() throws IOException { process.start(); assertTrue("alive", process.isAlive()); process.destroy(); assertFalse("alive", process.isAlive()); } @Test public void waits_until_the_expected_output_is_printed() throws IOException { OutputReader output = process.subscribeToOutput(); process.start(); assertTrue(output.waitForOutput("Runtime Environment")); } @Test public void returns_false_if_the_expected_output_is_not_printed() throws IOException { OutputReader output = process.subscribeToOutput(); process.start(); assertFalse(output.waitForOutput("will not be found")); } @Test public void continues_parsing_the_output_from_where_it_was_left() throws IOException { OutputReader output = process.subscribeToOutput(); process.start(); assertTrue(output.waitForOutput("Runtime")); assertTrue(output.waitForOutput(" Environment")); } @Test public void can_skip_buffered_output_without_processing_it() throws IOException { OutputReader output = process.subscribeToOutput(); process.start(); assertTrue(output.waitForOutput("Runtime")); output.skipBufferedOutput(); assertFalse(output.waitForOutput("Environment")); } @Test public void an_observer_can_see_what_the_process_prints_while_there_are_other_readers() throws IOException { OutputReader observer = process.subscribeToOutput(); OutputReader otherReader = process.subscribeToOutput(); process.start(); otherReader.waitForOutput("Environ"); otherReader.skipBufferedOutput(); String output = readFullyAsString(observer); assertTrue(output, output.contains("Runtime Environment")); } @Test public void if_two_threads_wait_concurrently_then_both_of_them_will_read_the_same_output() throws Exception { ExecutorService executor = Executors.newFixedThreadPool(2); Future<Boolean> t1 = executor.submit(new WaitForOutput("Runtime", process.subscribeToOutput())); Future<Boolean> t2 = executor.submit(new WaitForOutput("Runtime", process.subscribeToOutput())); process.start(); assertTrue("Thread 1 did not read it", t1.get()); assertTrue("Thread 2 did not read it", t2.get()); } private static String readFullyAsString(Reader source) throws IOException { StringWriter result = new StringWriter(); char[] buf = new char[1024]; int len; while ((len = source.read(buf)) != -1) { result.write(buf, 0, len); } return result.toString(); } private static class WaitForOutput implements Callable<Boolean> { private final String expected; private final OutputReader handle; public WaitForOutput(String expected, OutputReader handle) { this.expected = expected; this.handle = handle; } public Boolean call() throws Exception { return handle.waitForOutput(expected); } } }