blob: ba639e5395d45632e65dbdabae3345532723b338 [file] [log] [blame]
/*
* Copyright (c) 2014 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 com.google.common.base.Throwables;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Pattern;
import org.junit.ComparisonFailure;
import org.junit.rules.TestRule;
/**
* Extracted routines that need to be swapped in for GWT, to allow for minimal deltas between the
* GWT and non-GWT version.
*
* @author Christian Gruber (cgruber@google.com)
*/
final class Platform {
private Platform() {}
/** Returns true if the instance is assignable to the type Clazz. */
static boolean isInstanceOfType(Object instance, Class<?> clazz) {
return isInstanceOfTypeJava(instance, clazz);
}
/**
* Returns true if the instance is assignable to the type Clazz (suitable for a JVM environment).
*/
static boolean isInstanceOfTypeJava(Object instance, Class<?> clazz) {
return clazz.isInstance(instance);
}
/**
* Returns true if the instance is assignable to the type Clazz (suitable for a GWT environment).
*/
static boolean isInstanceOfTypeGWT(Object instance, Class<?> clazz) {
String className = clazz.getName();
Set<String> types = new LinkedHashSet<>();
types.add(instance.getClass().getCanonicalName());
addTypeNames(instance.getClass(), types);
return types.contains(className);
}
private static void addInterfaceNames(Class<?>[] interfaces, Set<String> types) {
for (Class<?> interfaze : interfaces) {
types.add(interfaze.getName());
addInterfaceNames(interfaze.getInterfaces(), types);
}
}
private static void addTypeNames(Class<?> clazz, Set<String> types) {
for (Class<?> current = clazz; current != null; current = current.getSuperclass()) {
types.add(current.getName());
addInterfaceNames(current.getInterfaces(), types);
}
}
static AssertionError comparisonFailure(
String message, String expected, String actual, Throwable cause) {
return new ComparisonFailureWithCause(message, expected, actual, cause);
}
/** Determines if the given subject contains a match for the given regex. */
static boolean containsMatch(String actual, String regex) {
return Pattern.compile(regex).matcher(actual).find();
}
/**
* Returns an array containing all of the exceptions that were suppressed to deliver the given
* exception. If suppressed exceptions are not supported (pre-Java 1.7), an empty array will be
* returned.
*/
static Throwable[] getSuppressed(Throwable throwable) {
try {
Method getSuppressed = throwable.getClass().getMethod("getSuppressed");
return (Throwable[]) getSuppressed.invoke(throwable);
} catch (NoSuchMethodException e) {
return new Throwable[0];
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
/**
* Returns true if stack trace cleaning is explicitly disabled in a system property. This switch
* os intended to be used when attempting to debug the frameworks which are collapsed or filtered
* out of stack traces by the cleaner.
*/
static boolean isStackTraceCleaningDisabled() {
return Boolean.parseBoolean(
System.getProperty("com.google.common.truth.disable_stack_trace_cleaning"));
}
private static final class ComparisonFailureWithCause extends ComparisonFailure {
/** Separate cause field, in case initCause() fails. */
private final Throwable cause;
ComparisonFailureWithCause(String message, String expected, String actual, Throwable cause) {
super(message, expected, actual);
this.cause = cause;
try {
initCause(cause);
} catch (IllegalStateException alreadyInitializedBecauseOfHarmonyBug) {
// See Truth.AssertionErrorWithCause.
}
}
@Override
@SuppressWarnings("UnsynchronizedOverridesSynchronized")
public Throwable getCause() {
return cause;
}
@Override
public String toString() {
return getLocalizedMessage();
}
}
static String doubleToString(double value) {
return Double.toString(value);
}
static String floatToString(float value) {
return Float.toString(value);
}
/** Returns a human readable string representation of the throwable's stack trace. */
static String getStackTraceAsString(Throwable throwable) {
return Throwables.getStackTraceAsString(throwable);
}
/** Tests if current platform is Android. */
static boolean isAndroid() {
return System.getProperties().getProperty("java.runtime.name").contains("Android");
}
/**
* Wrapping interface of {@link TestRule} to be used within truth.
*
* <p>Note that the sole purpose of this interface is to allow it to be swapped in GWT
* implementation.
*/
interface JUnitTestRule extends TestRule {}
}