
com.github.dakusui.actionunit.helpers.InternalUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of actionunit Show documentation
Show all versions of actionunit Show documentation
A library to build 'action' structure for testing
package com.github.dakusui.actionunit.helpers;
import com.github.dakusui.actionunit.exceptions.ActionException;
import org.junit.runners.Parameterized;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.TestClass;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.Supplier;
import java.util.stream.Collector;
import static com.github.dakusui.actionunit.exceptions.ActionException.wrap;
import static com.github.dakusui.actionunit.helpers.Checks.checkArgument;
import static com.github.dakusui.actionunit.helpers.Checks.checkNotNull;
import static java.lang.String.format;
import static java.util.Collections.singletonList;
public class InternalUtils {
public static T runWithTimeout(Callable callable, long timeout, TimeUnit timeUnit) {
final ExecutorService executor = Executors.newSingleThreadExecutor();
final Future future = executor.submit(callable);
executor.shutdown(); // This does not cancel the already-scheduled task.
try {
return future.get(timeout, timeUnit);
} catch (InterruptedException e) {
throw ActionException.wrap(e);
} catch (TimeoutException e) {
future.cancel(true);
throw ActionException.wrap(e);
} catch (ExecutionException e) {
//unwrap the root cause
Throwable cause = e.getCause();
if (cause instanceof Error) {
throw (Error) cause;
}
////
// It's safe to directly cast to RuntimeException, because a Callable can only
// throw an Error or a RuntimeException.
throw (RuntimeException) cause;
} finally {
executor.shutdownNow();
}
}
private static TimeUnit chooseTimeUnit(long intervalInNanos) {
// TimeUnit.values() returns elements of TimeUnit in declared order
// And they are declared in ascending order.
for (TimeUnit timeUnit : TimeUnit.values()) {
if (1000 > timeUnit.convert(intervalInNanos, TimeUnit.NANOSECONDS)) {
return timeUnit;
}
}
return TimeUnit.DAYS;
}
public static String formatDuration(long durationInNanos) {
TimeUnit timeUnit = chooseTimeUnit(durationInNanos);
return format("%d[%s]", timeUnit.convert(durationInNanos, TimeUnit.NANOSECONDS), timeUnit.toString().toLowerCase());
}
public static String shortClassNameOf(Class clazz) {
String name = checkNotNull(clazz).getName();
return name.substring(name.lastIndexOf('.') + 1);
}
public static String nonameIfNull(String summary) {
return summary == null
? "(noname)"
: summary;
}
public static String unknownIfNegative(int size) {
return size < 0
? "?"
: Integer.toString(size);
}
public static boolean isGivenTypeExpected_ArrayOfExpected_OrIterable(Class> expected, Class> actual) {
return expected.isAssignableFrom(actual)
|| (actual.isArray() && expected.isAssignableFrom(actual.getComponentType()))
|| Iterable.class.isAssignableFrom(actual);
}
/**
* Creates a {@code TestClass} object to mock {@code Parameterized} class's logic
* which cannot be overridden.
* Some IDE(s) (IntelliJ, for instance) treat classes that extend {@code Parameterized}
* runner in a special way. And therefore we have to extend it to allow users to
* use IDE features for parameterized runners.
*
* @param testClass original test class object.
* @return Created {@code TestClass} object.
*/
public static TestClass createTestClassMock(final TestClass testClass) {
return new TestClass(testClass.getJavaClass()) {
@Override
public List getAnnotatedMethods(final Class extends Annotation> annClass) {
if (Parameterized.Parameters.class.equals(annClass)) {
return singletonList(createDummyFrameworkMethod());
}
return super.getAnnotatedMethods(annClass);
}
private FrameworkMethod createDummyFrameworkMethod() {
return new FrameworkMethod(getDummyMethod()) {
public boolean isStatic() {
return true;
}
@Override
public Object invokeExplosively(Object target, Object... params) {
return new Object[] {};
}
@Override
public T getAnnotation(Class annotationType) {
checkArgument(Parameterized.Parameters.class.equals(annotationType));
//noinspection unchecked
return (T) new Parameterized.Parameters() {
@Override
public Class extends Annotation> annotationType() {
return Parameterized.Parameters.class;
}
@Override
public String name() {
return "{index}";
}
};
}
};
}
private Method getDummyMethod() {
return getToStringMethod(Object.class);
}
};
}
/**
* Tries to describe given {@code obj} in a best possible way.
*
* @param obj An object to be described.
* @return A description of {@code obj}.
*/
public static String describe(Object obj) {
if (obj == null) {
return "null";
}
if (getToStringMethod(obj.getClass()).equals(getToStringMethod(Object.class))) {
return describeClassOf(obj);
}
return obj.toString();
}
public static String summary(String s) {
return Objects.requireNonNull(s).length() > 40
? s.substring(0, 40) + "..."
: s;
}
private static String describeClassOf(Object obj) {
return shortClassNameOf(checkNotNull(obj).getClass());
}
public static void sleep(long duration, TimeUnit timeUnit) {
try {
checkNotNull(timeUnit).sleep(duration);
} catch (InterruptedException e) {
throw ActionException.wrap(e);
}
}
/**
* Returns a method without parameters which has a given {@code methodName} from
* a Class {@code klass}.
*
* @param klass A class from which method is searched.
* @param methodName A name of method to be returned.
* @return A method object of the specified name in the {@code klass}.
*/
public static Method getMethod(Class> klass, String methodName) {
try {
////
// Just chose "toString" because we know java.lang.Object has the method.
return checkNotNull(klass).getMethod(checkNotNull(methodName));
} catch (NoSuchMethodException e) {
throw wrap(e);
}
}
public static List toList(Iterable iterable) {
return new LinkedList() {{
for (T each : iterable)
add(each);
}};
}
private static Method getToStringMethod(Class> klass) {
return getMethod(klass, "toString");
}
public static boolean elementsEqual(Iterable> left, Iterable> right) {
Iterator iLeft = checkNotNull(left.iterator());
Iterator iRight = checkNotNull(right.iterator());
while (true) {
if (iLeft.hasNext()) {
if (!iRight.hasNext())
return false;
if (Objects.equals(iLeft.next(), iRight.next()))
continue;
return false;
}
return !iRight.hasNext();
}
}
public static Collector, Optional> singletonCollector(Supplier exceptionSupplier) throws E {
/*
* Borrowed from the following place.
* https://stackoverflow.com/questions/22694884/filter-java-stream-to-1-and-only-1-element
*/
return Collector.of(
ArrayList::new,
List::add,
(left, right) -> {
left.addAll(right);
return left;
},
list -> {
if (list.size() > 1)
throw exceptionSupplier.get();
return list.isEmpty()
? Optional.empty()
: Optional.of(list.get(0));
}
);
}
public static Supplier describable(String description, T value) {
return new Supplier() {
@Override
public T get() {
return value;
}
@Override
public String toString() {
return description;
}
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy