private String[] buildCommand() {
    List<String> list = new ArrayList<String>();

    list.add(context.getJavaExecutable());

    list.add("-cp");
    list.add(getClassPathAsString());

    list.add(getAgent());

    list.add("-Dpinpoint.agentId=build.test.0");
    list.add("-Dpinpoint.applicationName=test");
    list.add("-D" + PinpointPluginTestConstants.PINPOINT_TEST_ID + "=" + testCase.getTestId());

    for (String arg : context.getJvmArguments()) {
      list.add(arg);
    }

    if (context.isDebug()) {
      list.addAll(getDebugOptions());
    }

    if (context.getConfigFile() != null) {
      list.add("-Dpinpoint.config=" + context.getConfigFile());
    }

    for (String arg : testCase.getVmArgs()) {
      list.add(arg);
    }

    String mainClass = testCase.getMainClass();

    if (mainClass.endsWith(".jar")) {
      list.add("-jar");
    }

    list.add(mainClass);
    list.addAll(testCase.getAppArgs());

    return list.toArray(new String[list.size()]);
  }
  private String getClassPathAsString() {
    StringBuilder classPath = new StringBuilder();
    boolean first = true;

    for (String lib : testCase.getClassPath()) {
      if (first) {
        first = false;
      } else {
        classPath.append(File.pathSeparatorChar);
      }

      classPath.append(lib);
    }

    return classPath.toString();
  }
  @Override
  public void evaluate() throws Throwable {
    ProcessBuilder builder = new ProcessBuilder();

    builder.command(buildCommand());
    builder.redirectErrorStream(true);
    builder.directory(testCase.getWorkingDirectory());

    System.out.println("Working directory: " + SystemProperty.INSTANCE.getProperty("user.dir"));
    System.out.println("Command: " + builder.command());

    Description parentDescription = runner.getDescription();

    final Process process = builder.start();

    try {
      Scanner scanner = testCase.startTest(process);

      while (scanner.hasNextLine()) {
        String line = scanner.nextLine();

        if (line.startsWith(JUNIT_OUTPUT_DELIMITER)) {
          System.out.println(line);
          String[] tokens = line.split(JUNIT_OUTPUT_DELIMITER_REGEXP);
          String event = tokens[1];

          if ("testRunStarted".equals(event)) {
            notifier.fireTestRunStarted(parentDescription);
          } else if ("testRunFinished".equals(event)) {
            notifier.fireTestRunFinished(result);
          } else if ("testStarted".equals(event)) {
            Description ofTest = findDescription(parentDescription, tokens[2]);
            notifier.fireTestStarted(ofTest);
          } else if ("testFinished".equals(event)) {
            Description ofTest = findDescription(parentDescription, tokens[2]);
            notifier.fireTestFinished(ofTest);
          } else if ("testFailure".equals(event)) {
            List<String> stackTrace =
                tokens.length > 5
                    ? Arrays.asList(tokens).subList(5, tokens.length - 1)
                    : Collections.<String>emptyList();
            Failure failure =
                toFailure(parentDescription, tokens[2], tokens[3], tokens[4], stackTrace);
            notifier.fireTestFailure(failure);
          } else if ("testAssumptionFailure".equals(event)) {
            List<String> stackTrace =
                tokens.length > 5
                    ? Arrays.asList(tokens).subList(5, tokens.length - 1)
                    : Collections.<String>emptyList();
            Failure failure =
                toFailure(parentDescription, tokens[2], tokens[3], tokens[4], stackTrace);
            notifier.fireTestAssumptionFailed(failure);
          } else if ("testIgnored".equals(event)) {
            Description ofTest = findDescription(parentDescription, tokens[2]);
            notifier.fireTestIgnored(ofTest);
          }
        } else {
          System.out.println(line);
        }
      }
    } catch (Throwable t) {
      System.err.println("Failed to execute test");
      t.printStackTrace();

      throw t;
    } finally {
      try {
        testCase.endTest(process);
      } finally {

        Timer timer = new Timer();
        timer.schedule(
            new TimerTask() {

              @Override
              public void run() {
                process.destroy();
              }
            },
            10 * 1000);

        try {
          process.waitFor();
        } catch (InterruptedException e) {
          // ignore
        }

        timer.cancel();
      }
    }
  }