package crate.elasticsearch.export; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; import java.util.List; import org.junit.Test; import crate.elasticsearch.export.Output.Result; /** * Tests for the @OutputCommand class. These tests currently call * UNIX commands and are only executable on Linux/MacOS Systems. */ public class OutputCommandTest { /** * The getOutputstream() method returns null if the command * has not been opened yet. */ @Test public void testWithoutStart() { OutputCommand outputCommand = new OutputCommand("cat", false); assertNull(outputCommand.getOutputStream()); } /** * A not existing command raises an IO exception when opening. */ @Test public void testErrorCommand() { OutputCommand outputCommand = new OutputCommand("_notexistingcommand", false); // Start the process try { outputCommand.open(); } catch (IOException e) { // The command does not exist and should raise an IOException return; } fail("Test should raise IOException"); } /** * A single command can not have arguments. 'Cat' returns the input * to it's output stream. The first 8K of the output stream will be * captured by the stream consumer and shown in the result. */ @Test public void testSingleCommand() throws IOException { // Create a 'cat' output command. The cat command puts // the standard in strings to the standard out OutputCommand outputCommand = new OutputCommand("cat", false); // Start the process try { outputCommand.open(); } catch (IOException e) { e.printStackTrace(); fail("Method start() failed due to IOException"); } // Add a bunch of lines to the process' standard in. OutputStream os = outputCommand.getOutputStream(); for (int i = 0; i < 1000000; i++) { String string = "Line " + i +"\n"; os.write(string.getBytes()); } // Finish the process outputCommand.close(); Result result = outputCommand.result(); // There is a result object assertNotNull(result); // The exit status of the process is 0 assertEquals(0, result.exit); // There is no error in the standard error log assertEquals("", result.stdErr); // The first 8K of the standard out are captured assertTrue(result.stdOut.endsWith("Line 922\n")); } /** * A list of commands allow arguments to a process. Do a shell script * and write to a file. */ @Test public void testCommandList() throws IOException { // For multiple commands use the list constructor. String filename = "/tmp/outputcommand.txt"; List<String> cmds = Arrays.asList("/bin/sh", "-c", "cat > " + filename); OutputCommand outputCommand = new OutputCommand(cmds, false); // Start the process outputCommand.open(); // Add a bunch of lines to the process' standard in. OutputStream os = outputCommand.getOutputStream(); for (int i = 0; i < 1000000; i++) { String string = "Line " + i +"\n"; os.write(string.getBytes()); } // Finish the process outputCommand.close(); Result result = outputCommand.result(); // The exit status of the process is 127 assertEquals(0, result.exit); // The error output is captured assertEquals("", result.stdErr); // The standard output of the process is empty assertEquals("", result.stdOut); // The command has been executed and written data to the file assertEquals(11888890, new File(filename).length()); new File(filename).delete(); } /** * Writing to a failed/quit process will lead to an IOException * as soon as the process is finished. */ @Test public void testWriteToFailedCommand() throws IOException { OutputCommand outputCommand = new OutputCommand("rm", false); // Start the process outputCommand.open(); // Add a bunch of lines to the process' standard in. OutputStream os = outputCommand.getOutputStream(); try { for (int i=0; i< 1048576; i++) { os.write(65); } } catch (IOException e) { return; } fail("Writing to failed process did not throw IOException"); } /** * A failed command will have an exit status and capture the error log. */ @Test public void testFailedCommandResult() throws IOException { OutputCommand outputCommand = new OutputCommand("rm", false); // Start the process outputCommand.open(); outputCommand.close(); Result result = outputCommand.result(); // There is a result object assertNotNull(result); // The exit status of the process is not 0 assertTrue(result.exit != 0); // There error message is in the standard error log assertTrue(result.stdErr.length() > 0); // The standard output is empty assertEquals("", result.stdOut); } /** * The gzip parameter zips the output to the standard in of the * process. The 'gunzip' command unzips the result, and therefore * must be readable again. */ @Test public void testSingleCommandGZipped() throws IOException { // Create a 'cat' output command. The cat command puts // the standard in strings to the standard out OutputCommand outputCommand = new OutputCommand("gunzip", true); // Start the process try { outputCommand.open(); } catch (IOException e) { e.printStackTrace(); fail("Method start() failed due to IOException"); } // Add a bunch of lines to the process' standard in. OutputStream os = outputCommand.getOutputStream(); for (int i = 0; i < 1000000; i++) { String string = "Line " + i +"\n"; os.write(string.getBytes()); } // Finish the process outputCommand.close(); Result result = outputCommand.result(); // There is a result object assertNotNull(result); // The exit status of the process is 0 assertEquals(0, result.exit); // There is no error in the standard error log assertEquals("", result.stdErr); // The first 8K of the standard out are captured assertTrue(result.stdOut.endsWith("Line 922\n")); } }