package org.smoothbuild.lang.function.nativ;
import static java.util.Arrays.asList;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.instanceOf;
import static org.smoothbuild.lang.function.nativ.TestingUtils.function;
import static org.smoothbuild.task.exec.ContainerImpl.containerImpl;
import static org.testory.Testory.given;
import static org.testory.Testory.then;
import static org.testory.Testory.thenReturned;
import static org.testory.Testory.thenThrown;
import static org.testory.Testory.when;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.junit.Test;
import org.smoothbuild.lang.message.ErrorMessage;
import org.smoothbuild.lang.message.Message;
import org.smoothbuild.lang.message.WarningMessage;
import org.smoothbuild.lang.plugin.Container;
import org.smoothbuild.lang.plugin.SmoothFunction;
import org.smoothbuild.lang.value.SString;
import org.smoothbuild.lang.value.Value;
import org.smoothbuild.task.exec.ContainerImpl;
import com.google.common.hash.HashCode;
public class NativeFunctionInvokeTest {
private NativeFunction function;
private ContainerImpl container;
private SString string;
private Method method;
@Test
public void invoke_returns_result_from_invokation_of_native_java_method() throws Exception {
given(container = containerImpl());
given(function = function(StringFunction.class));
when(function).invoke(container, asList());
thenReturned(container.create().string("abc"));
}
public static class StringFunction {
@SmoothFunction
public static SString stringFunction(Container container) {
return container.create().string("abc");
}
}
@Test
public void invoke_passes_arguments_to_java_method() throws Exception {
given(container = containerImpl());
given(function = function(StringIdentity.class));
given(string = container.create().string("abc"));
when(function).invoke(container, Arrays.<Value> asList(string));
thenReturned(container.create().string("abc"));
}
public static class StringIdentity {
@SmoothFunction
public static SString stringIdentity(Container container, SString string) {
return string;
}
}
@Test
public void error_reported_by_java_method_is_logged() throws Exception {
given(container = containerImpl());
given(function = function(ErrorReporting.class));
when(function).invoke(container, asList());
then(container.messages(), contains(instanceOf(MyError.class)));
}
public static class ErrorReporting {
@SmoothFunction
public static SString errorReporting(Container container) {
container.log(new MyError());
return null;
}
}
public static class MyError extends ErrorMessage {
public MyError() {
super("");
}
}
@Test
public void invoke_logs_error_when_java_method_returns_null_without_logging_error()
throws Exception {
given(container = containerImpl());
given(function = function(NullReturning.class));
when(function).invoke(container, asList());
then(container.messages(), contains(instanceOf(Message.class)));
}
public static class NullReturning {
@SmoothFunction
public static SString nullReturning(Container container) {
return null;
}
}
@Test
public void invoke_logs_error_when_java_method_returns_null_and_logs_only_warning()
throws Exception {
given(container = containerImpl());
given(function = function(WarningReporting.class));
when(function).invoke(container, asList());
then(container.messages(), contains(instanceOf(MyWarning.class), instanceOf(Message.class)));
}
public static class WarningReporting {
@SmoothFunction
public static SString warningReporting(Container container) {
container.log(new MyWarning());
return null;
}
}
public static class MyWarning extends WarningMessage {
public MyWarning() {
super("");
}
}
@Test
public void invoke_rethrows_illegal_access_exception_wrapped_inside_runtimeException()
throws Exception {
given(container = containerImpl());
given(function = function(NormalFunction.class));
given(method = PrivateMethod.class.getDeclaredMethods()[0]);
given(function = new NativeFunction(method, function.signature(), true, HashCode.fromInt(13)));
when(function).invoke(container, asList());
thenThrown(RuntimeException.class);
}
public static class NormalFunction {
@SmoothFunction
public static SString function(Container container) {
return null;
}
}
public static class PrivateMethod {
@SuppressWarnings("unused")
private static SString function(Container container) {
return null;
}
}
@Test
public void invoke_rethrows_normal_exception_wrapped_inside_runtime_exception() throws Exception {
given(container = containerImpl());
given(function = function(ThrowNormalExceptiton.class));
when(function).invoke(container, asList());
thenThrown(RuntimeException.class);
}
public static class ThrowNormalExceptiton {
@SmoothFunction
public static SString throwNormalException(Container container) throws Exception {
throw new Exception();
}
}
@Test
public void invoke_rethrows_runtime_exception_as_wrapped_inside_runtime_exception()
throws Exception {
given(container = containerImpl());
given(function = function(ThrowRuntimeExceptiton.class));
when(function).invoke(container, asList());
thenThrown(RuntimeException.class);
}
public static class ThrowRuntimeExceptiton {
@SmoothFunction
public static SString throwRuntimeException(Container container) {
throw new RuntimeException();
}
}
@Test
public void invoke_adds_thrown_messages_to_logged_messages() throws Exception {
given(container = containerImpl());
given(function = function(ThrowMessage.class));
when(function).invoke(container, asList());
then(container.messages(), contains(instanceOf(MyError.class)));
}
public static class ThrowMessage {
@SmoothFunction
public static SString throwMessage(Container container) {
throw new MyError();
}
}
}