/* * Copyright (c) 2011 Google, 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.google.common.truth; import java.util.Arrays; /** * A {@code FailureStrategy} defines how assertion failures are handled. In {@link Truth}, failures * {@linkplain Truth#THROW_ASSERTION_ERROR throw AssertionErrors}; other assertion entry-points like * {@link Expect} and {@link TruthJUnit#assume} have different failure behavior. * * <p>It should generally be unnecessary for Truth SPI developers to define their own {@code * FailureStrategy} implementations, they should instead use {@link Subject#check} to invoke other * subjects using the current strategy. When you really do need to creatae your own strategy prefer * to extend {@link AbstractFailureStrategy} rather than this class directly. * * <p>Implementation Note: the concrete methods in this class will be made abstract in the near * future (see b/37472530); please do not depend on these existing implementations in new code, * prefer {@code AbstractFailureStrategy}. */ public abstract class FailureStrategy { /** * Report an assertion failure with a text message. This method should generally delegate to * {@link #fail(String, Throwable)}. */ public void fail(String message) { fail(message, null); } /** * Report an assertion failure with a text message and a throwable that indicates the cause of the * failure. This will be reported as the cause of the exception raised by this method (if one is * thrown) or otherwise recorded by the strategy as the underlying cause of the failure. */ public void fail(String message, Throwable cause) { AssertionError up = new AssertionError(message); if (cause == null) { cause = new AssertionError(message); } try { up.initCause(cause); } catch (IllegalStateException alreadyInitializedBecauseOfHarmonyBug) { // https://code.google.com/p/android/issues/detail?id=29378 // No message, but it's the best we can do without awful hacks. throw new AssertionError(cause); } stripTruthStackFrames(up); throw up; } /** * Convenience method to report string-comparison failures with more detail (e.g. character * differences). This method should generally delegate to {@link #failComparing(String, * CharSequence, CharSequence, Throwable)}. */ public void failComparing(String message, CharSequence expected, CharSequence actual) { failComparing(message, expected, actual, null); } /** * Convenience method to report string-comparison failures with more detail (e.g. character * differences), along with a throwable that indicates the cause of the failure. This will be * reported as the cause of the exception raised by this method (if one is thrown) or otherwise * recorded by the strategy as the underlying cause of the failure. */ public void failComparing( String message, CharSequence expected, CharSequence actual, Throwable cause) { fail(StringUtil.messageFor(message, expected, actual), cause); } /** * Strips stack frames from the throwable that have a class starting with com.google.common.truth. */ private static void stripTruthStackFrames(Throwable throwable) { StackTraceElement[] stackTrace = throwable.getStackTrace(); int i = 0; while (i < stackTrace.length && stackTrace[i].getClassName().startsWith("com.google.common.truth")) { i++; } throwable.setStackTrace(Arrays.copyOfRange(stackTrace, i, stackTrace.length)); } }