package org.smoothbuild.lang.function.nativ;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static org.hamcrest.Matchers.contains;
import static org.smoothbuild.lang.function.base.Name.name;
import static org.smoothbuild.lang.function.nativ.NativeLibraryLoader.loadNativeModules;
import static org.smoothbuild.util.Classes.binaryPath;
import static org.testory.Testory.thenReturned;
import static org.testory.Testory.thenThrown;
import static org.testory.Testory.when;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.smoothbuild.lang.function.base.Function;
import org.smoothbuild.lang.function.base.Name;
import org.smoothbuild.lang.plugin.Container;
import org.smoothbuild.lang.plugin.SmoothFunction;
import org.smoothbuild.lang.value.SString;
import org.smoothbuild.util.Classes;
import com.google.common.io.ByteStreams;
public class NativeLibraryLoaderTest {
@Test
public void module_with_zero_functions_is_allowed() throws Exception {
when(loadNativeModules(asList(module(ModuleWithNoFunctions.class))));
thenReturned(Matchers.emptyIterable());
}
public static class ModuleWithNoFunctions {}
@Test
public void all_functions_are_loaded() throws Exception {
when(toNames(loadNativeModules(asList(module(TwoFunctions.class)))));
thenReturned(contains(name("func1"), name("func2")));
}
public static class TwoFunctions {
public interface Parameters {}
@SmoothFunction
public static SString func1(Container container) {
return null;
}
@SmoothFunction
public static SString func2(Container container) {
return null;
}
}
@Test
public void loading_module_with_two_functions_with_the_same_name_fails() throws Exception {
when(() -> loadNativeModules(asList(module(FunctionA.class, FunctionA2.class))));
thenThrown(IllegalArgumentException.class);
}
@Test
public void loading_two_modules_having_function_with_the_same_name_fails() throws Exception {
when(() -> loadNativeModules(asList(module(FunctionA.class), module(FunctionA2.class))));
thenThrown(IllegalArgumentException.class);
}
public static class FunctionA {
@SmoothFunction
public static SString funcA(Container container) {
return null;
}
}
public static class FunctionA2 {
@SmoothFunction
public static SString funcA(Container container) {
return null;
}
}
private static Path module(Class<?>... classes) throws IOException,
FileNotFoundException {
File tempJarFile = File.createTempFile("tmp", ".jar");
try (JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(tempJarFile))) {
for (Class<?> clazz : classes) {
jarOutputStream.putNextEntry(new ZipEntry(binaryPath(clazz)));
try (InputStream byteCodeInputStream = Classes.byteCodeAsInputStream(clazz)) {
ByteStreams.copy(byteCodeInputStream, jarOutputStream);
}
}
}
return tempJarFile.toPath();
}
private static List<Name> toNames(Collection<Function> functions) {
return functions.stream().map(Function::name).collect(toList());
}
}