static RunListener createSingleTestResultRunListener()

in src/com/facebook/buck/junit/TestResult.java [65:158]


  static RunListener createSingleTestResultRunListener(final List<TestResult> results) {
    return new RunListener() {

      private PrintStream originalOut, originalErr, stdOutStream, stdErrStream;
      private ByteArrayOutputStream rawStdOutBytes, rawStdErrBytes;
      private Result result;
      private RunListener resultListener;

      @Override
      public void testStarted(Description description) throws Exception {
        // Create an intermediate stdout/stderr to capture any debugging statements (usually in the
        // form of System.out.println) the developer is using to debug the test.
        originalOut = System.out;
        originalErr = System.err;
        rawStdOutBytes = new ByteArrayOutputStream();
        rawStdErrBytes = new ByteArrayOutputStream();
        stdOutStream = new PrintStream(
            rawStdOutBytes, true /* autoFlush */, ENCODING);
        stdErrStream = new PrintStream(
            rawStdErrBytes, true /* autoFlush */, ENCODING);
        System.setOut(stdOutStream);
        System.setErr(stdErrStream);

        // Prepare single-test result.
        result = new Result();
        resultListener = result.createListener();
        resultListener.testRunStarted(description);
        resultListener.testStarted(description);
      }

      @Override
      public void testFinished(Description description) throws Exception {
        // Shutdown single-test result.
        resultListener.testFinished(description);
        resultListener.testRunFinished(result);
        resultListener = null;

        // Restore the original stdout/stderr.
        System.setOut(originalOut);
        System.setErr(originalErr);

        // Get the stdout/stderr written during the test as strings.
        stdOutStream.flush();
        stdErrStream.flush();

        int numFailures = result.getFailureCount();
        String className = description.getClassName();
        String methodName = description.getMethodName();
        // In practice, I have seen one case of a test having more than one failure:
        // com.xtremelabs.robolectric.shadows.H2DatabaseTest#shouldUseH2DatabaseMap() had 2 failures.
        // However, I am not sure what to make of it, so we let it through.
        if (numFailures < 0) {
          throw new IllegalStateException(String.format(
              "Unexpected number of failures while testing %s#%s(): %d (%s)",
              className,
              methodName,
              numFailures,
              result.getFailures()));
        }
        Failure failure = numFailures == 0 ? null : result.getFailures().get(0);

        String stdOut = rawStdOutBytes.size() == 0 ? null : rawStdOutBytes.toString(ENCODING);
        String stdErr = rawStdErrBytes.size() == 0 ? null : rawStdErrBytes.toString(ENCODING);

        results.add(new TestResult(className,
            methodName,
            result.getRunTime(),
            failure,
            stdOut,
            stdErr));
      }

      @Override
      public void testAssumptionFailure(Failure failure) {
        if (resultListener != null) {
          resultListener.testAssumptionFailure(failure);
        }
      }

      @Override
      public void testFailure(Failure failure) throws Exception {
        if (resultListener != null) {
          resultListener.testFailure(failure);
        }
      }

      @Override
      public void testIgnored(Description description) throws Exception {
        if (resultListener != null) {
          resultListener.testIgnored(description);
        }
      }
    };
  }