private void runTests(final String[] command) {
    LOGGER.fine(
        () -> "Starting execute tests with command: " + String.join(" ", Arrays.asList(command)));
    final Consumer<String> consumer =
        new Consumer<String>() {
          private String currentTestName;

          @Override
          public void accept(final String line) {
            final TestOutputParser.Result result = parser.parseOutputLine(line);
            if (result != null) {
              if (result.testState == TestRunState.RUNNING) {
                currentTestName = result.testName;
              }
              testRunnerHandlers
                  .stream()
                  .forEach(handler -> handler.onTestStateChange(result.testName, result.testState));
            }
            testRunnerHandlers
                .stream()
                .forEach(handler -> handler.onOutputLine(currentTestName, line));

            if (result != null && result.testState != TestRunState.RUNNING) {
              currentTestName = null;
            }
          }
        };

    testRunnerHandlers.stream().forEach(TestRunnerHandler::onTestRunStart);
    boolean hasSucceed = false;
    try {
      final int exitCode = processRunner.start(command, consumer);
      if (exitCode == 0) {
        hasSucceed = true;
        LOGGER.fine("Test run exits with normal code");
      } else {
        LOGGER.info("Test run exits with " + exitCode + " code");
      }
    } catch (IOException e) {
      LOGGER.warning("Test run process throws exception: " + e.getMessage());
    } finally {
      for (TestRunnerHandler handler : testRunnerHandlers) {
        handler.onTestRunFinished(hasSucceed);
      }
    }
  }
  private void readBinary(final String[] command) {
    LOGGER.fine(
        () -> "Starting reading binary with command: " + String.join(" ", Arrays.asList(command)));
    final Collection<String> lines = new ArrayList<>();

    boolean hasSucceed = false;
    Collection<String> testNames = Collections.emptyList();
    try {
      final int exitCode = processRunner.start(command, lines::add);
      if (exitCode == 0) {
        testNames = parser.parseTestList(lines);
        hasSucceed = true;
        LOGGER.fine("Reading binary process exits with normal code");
      } else {
        LOGGER.warning("Reading binary process exits with " + exitCode + " code");
      }
    } catch (IOException | ParseException e) {
      LOGGER.warning("Reading binary process throws exception: " + e.getMessage());
    } finally {
      for (TestRunnerHandler handler : testRunnerHandlers) {
        handler.onTestsLoadingFinished(hasSucceed, testNames);
      }
    }
  }
 public void stop() {
   if (processRunner != null) {
     LOGGER.info("Stopping process");
     processRunner.cancel();
   }
 }