/**
   * Test method for {@link com.buildml.utils.os.SystemUtils#executeShellCmd(java.lang.String[],
   * java.lang.String)}.
   *
   * @throws InterruptedException
   * @throws IOException
   */
  @Test
  public void testExecuteShellCmd() throws IOException, InterruptedException {

    ShellResult sr;

    /* Execute an invalid command - should return an IOException */
    try {
      sr = SystemUtils.executeShellCmd(new String[] {"/blah"}, "Hello World\n");
      fail("Failed to throw IOException when executing invalid command");
    } catch (IOException ex) {
      /* passed */
    }

    /* request a specific error code - our perl script always does exit() with it's second argument */
    sr = SystemUtils.executeShellCmd(new String[] {ourTempExe.toString(), "0", "23"}, "\n");
    assertEquals(sr.getReturnCode(), 23);

    /* Simply echo back our stdin - the stdout should be identical to the stdin we provided. */
    sr =
        SystemUtils.executeShellCmd(
            new String[] {ourTempExe.toString(), "0", "0"}, "Hello World\n");
    assertEquals(sr.getReturnCode(), 0);
    assertEquals("Hello World\n", sr.getStdout());
    assertEquals("", sr.getStderr());

    /* Same, but with multiple lines of text. */
    sr =
        SystemUtils.executeShellCmd(
            new String[] {ourTempExe.toString(), "0", "0"}, "Hello World\nHow are you?\n");
    assertEquals(sr.getReturnCode(), 0);
    assertEquals("Hello World\nHow are you?\n", sr.getStdout());
    assertEquals("", sr.getStderr());

    /*
     * Now get the program to generate some of its own output - that is, 5 letters on stdout
     * and 5 digits on stderr.
     */
    sr = SystemUtils.executeShellCmd(new String[] {ourTempExe.toString(), "5", "0"}, "Hi\n");
    assertEquals(sr.getReturnCode(), 0);
    assertEquals("Hi\nABCDE\n", sr.getStdout());
    assertEquals("01234\n", sr.getStderr());

    /*
     * Now try a really really big case, where the stdout and stderr will certainly be intermingled.
     */
    int count = 250000;
    sr =
        SystemUtils.executeShellCmd(
            new String[] {ourTempExe.toString(), String.valueOf(count)}, "");
    assertEquals(sr.getReturnCode(), 0);

    /* first, check the lengths */
    String stdOut = sr.getStdout();
    String stdErr = sr.getStderr();
    assertEquals(count + 1, stdOut.length()); /* include the trailing \n */
    assertEquals(count + 1, stdErr.length());

    /* now check each individual character of what was returned */
    for (int i = 0; i != count; i++) {
      char ch = stdOut.charAt(i);
      int num = (int) stdErr.charAt(i) - '0';
      assertEquals('A' + (i % 26), ch);
      assertEquals(i % 10, num);
    }

    /*
     * Test the non-buffering variant. Even though there's output, we shouldn't get any
     * of it.
     */
    sr =
        SystemUtils.executeShellCmd(
            new String[] {ourTempExe.toString(), "0", "0"}, "Hello World\n", null, false, null);
    assertEquals(sr.getReturnCode(), 0);
    assertEquals("", sr.getStdout());
    assertEquals("", sr.getStderr());

    /*
     * Test with an invalid working directory
     */
    try {
      sr =
          SystemUtils.executeShellCmd(
              new String[] {ourTempExe.toString(), "0", "0"},
              "Hello World\n",
              null,
              false,
              new File("/invalid-path"));
      fail("Failed to throw IOException when executing in invalid directory.");
    } catch (IOException ex) {
      /* passed */
    }

    /*
     * Test with a valid working directory
     */
    sr =
        SystemUtils.executeShellCmd(
            new String[] {ourTempExe.toString(), "0", "0"},
            "Hello World\n",
            null,
            false,
            new File("/tmp"));
    assertEquals(sr.getReturnCode(), 0);
    assertEquals("", sr.getStdout());
    assertEquals("", sr.getStderr());

    /*
     * Note: we can't automatically test the echoToOutput option, unless we had a way to
     * observe our own standard output.
     */
  }