| /* |
| * Copyright 2012-present Facebook, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may |
| * not use this file except in compliance with the License. You may obtain |
| * a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package com.facebook.buck.junit; |
| |
| import org.junit.runner.Result; |
| import org.junit.runner.notification.Failure; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.PrintStream; |
| import java.lang.reflect.Method; |
| import java.util.concurrent.Callable; |
| |
| /** |
| * Result of an individual test method in JUnit. Similar to {@link Result}, except that it always |
| * corresponds to exactly one test method. |
| */ |
| final class TestResult { |
| |
| private static final String ENCODING = "UTF-8"; |
| |
| final String testClassName; |
| final String testMethodName; |
| final long runTime; |
| final /* @Nullable */ Failure failure; |
| final /* @Nullable */ String stdOut; |
| final /* @Nullable */ String stdErr; |
| |
| public TestResult(String testClassName, |
| String testMethodName, |
| long runTime, |
| Failure failure, |
| /* @Nullable */ String stdOut, |
| /* @Nullable */ String stdErr) { |
| this.testClassName = testClassName; |
| this.testMethodName = testMethodName; |
| this.runTime = runTime; |
| this.failure = failure; |
| this.stdOut = stdOut; |
| this.stdErr = stdErr; |
| } |
| |
| public boolean isSuccess() { |
| return failure == null; |
| } |
| |
| /** |
| * Runs the specified test method using the specified test runner. |
| */ |
| static TestResult runTestMethod(Callable<Result> runTestAndProduceJUnitResult, Method testMethod) |
| 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. |
| PrintStream originalOut = System.out; |
| PrintStream originalErr = System.err; |
| ByteArrayOutputStream rawStdOutBytes = new ByteArrayOutputStream(); |
| ByteArrayOutputStream rawStdErrBytes = new ByteArrayOutputStream(); |
| PrintStream stdOutStream = new PrintStream( |
| rawStdOutBytes, true /* autoFlush */, ENCODING); |
| PrintStream stdErrStream = new PrintStream( |
| rawStdErrBytes, true /* autoFlush */, ENCODING); |
| System.setOut(stdOutStream); |
| System.setErr(stdErrStream); |
| |
| // Run the test! |
| Result result = runTestAndProduceJUnitResult.call(); |
| |
| // 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 = testMethod.getDeclaringClass().getCanonicalName(); |
| String methodName = testMethod.getName(); |
| // 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); |
| return new TestResult(className, |
| methodName, |
| result.getRunTime(), |
| failure, |
| stdOut, |
| stdErr); |
| } |
| } |