package org.smoothbuild.lang.function.nativ;
import static org.smoothbuild.lang.function.nativ.NativeFunctionFactory.nativeFunctions;
import static org.smoothbuild.lang.function.nativ.TestingUtils.function;
import static org.smoothbuild.testing.common.ExceptionMatcher.exception;
import static org.testory.Testory.given;
import static org.testory.Testory.thenReturned;
import static org.testory.Testory.thenThrown;
import static org.testory.Testory.when;
import org.junit.Test;
import org.smoothbuild.lang.plugin.Container;
import org.smoothbuild.lang.plugin.Required;
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 NativeFunctionParameterTest {
private NativeFunction function;
@Test
public void parameter_name_is_taken_from_java_parameter_name() throws Exception {
given(function = function(Name.class));
when(function.parameters().get(0).name());
thenReturned("parameter");
}
public static class Name {
@SmoothFunction
public static SString function(Container container, SString parameter) {
return null;
}
}
@Test
public void method_without_native_api_parameter_causes_exception() throws Exception {
when(() -> nativeFunctions(MissingContainer.class, HashCode.fromInt(13)));
thenThrown(exception(new NativeFunctionImplementationException(
MissingContainer.class.getMethod("function"),
"Its first parameter should have '" + Container.class.getCanonicalName() + "' type.")));
}
public static class MissingContainer {
@SmoothFunction
public static SString function() {
return null;
}
}
@Test
public void method_with_first_parameter_that_is_not_native_api_causes_exception()
throws Exception {
when(() -> nativeFunctions(NotContainer.class, HashCode.fromInt(13)));
thenThrown(exception(new NativeFunctionImplementationException(
NotContainer.class.getMethod("function", SString.class),
"Its first parameter should have '" + Container.class.getCanonicalName() + "' type.")));
}
public static class NotContainer {
@SmoothFunction
public static SString function(SString parameter) {
return null;
}
}
@Test
public void method_with_first_parameter_that_is_native_api_impl_is_accepted() throws Exception {
when(nativeFunctions(WithContainerImpl.class, HashCode.fromInt(13)));
thenReturned();
}
public static class WithContainerImpl {
@SmoothFunction
public static SString function(ContainerImpl container) {
return null;
}
}
@Test
public void method_with_illegal_parameter_type_causes_exception() throws Exception {
when(() -> nativeFunctions(IllegalType.class, HashCode.fromInt(13)));
thenThrown(exception(new NativeFunctionImplementationException(
IllegalType.class.getMethod("function", Container.class, Object.class),
"It has parameter with illegal java type 'java.lang.Object'.")));
}
public static class IllegalType {
@SmoothFunction
public static SString function(Container container, Object parameter) {
return null;
}
}
@Test
public void method_with_parameter_with_value_type_causes_exception() throws Exception {
when(() -> nativeFunctions(ValueType.class, HashCode.fromInt(13)));
thenThrown(exception(new NativeFunctionImplementationException(
ValueType.class.getMethod("function", Container.class, Value.class),
"It has parameter with illegal java type 'org.smoothbuild.lang.value.Value'.")));
}
public static class ValueType {
@SmoothFunction
public static SString function(Container container, Value parameter) {
return null;
}
}
@Test
public void parameter_is_not_required_by_default() throws Exception {
given(function = function(NotRequiredParameter.class));
when(function.parameters().get(0).isRequired());
thenReturned(false);
}
public static class NotRequiredParameter {
@SmoothFunction
public static SString function(Container container, SString parameter) {
return null;
}
}
@Test
public void parameter_annotated_with_required_annotation_is_required() throws Exception {
given(function = function(RequiredParameter.class));
when(function.parameters().get(0).isRequired());
thenReturned(true);
}
public static class RequiredParameter {
@SmoothFunction
public static SString function(Container container, @Required SString parameter) {
return null;
}
}
}