package scotch.runner;
import static org.apache.commons.io.FileUtils.deleteDirectory;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static scotch.runtime.RuntimeSupport.box;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import org.apache.commons.cli.ParseException;
import org.junit.Before;
import org.junit.Test;
import scotch.runtime.Applicable;
import scotch.runtime.Callable;
public class CompilerRunnerTest {
private static final String OUTPUT_PATH = "build/generated-test-classes/CompilerRunnerTest";
@Before
public void setUp() throws IOException {
deleteDirectory(new File(OUTPUT_PATH));
}
@Test
public void shouldCompileFiles() throws Exception {
compile();
shouldHaveClasses(
"a.b.c.$$Module",
"x.y.z.$$Module",
"a.b.c.Toast",
"a.b.c.Toast$Toast",
"a.b.c.Bread",
"a.b.c.Bread$Rye",
"a.b.c.Bread$Wheat",
"a.b.c.Bread$White"
);
}
@SuppressWarnings("unchecked")
@Test
public void toastWithBurnLevelOf4ShouldBeBurned() throws Exception {
compile();
ClassLoader classLoader = getClassLoader();
Method rye = classLoader.loadClass("a.b.c.$$Module").getMethod("Rye");
Callable toast = getToast(classLoader, rye);
Method isBurned = classLoader.loadClass("x.y.z.$$Module").getMethod("isBurned$wat");
assertThat(((Applicable) isBurned.invoke(null)).apply(toast).call(), is(true));
}
private void compile() throws ParseException, IOException {
CompilerRunner.main(new String[] {
"-o", OUTPUT_PATH,
"src/test/resources/CompilerRunnerTest/file1.scotch",
"src/test/resources/CompilerRunnerTest/file2.scotch",
"src/test/resources/CompilerRunnerTest/file3.scotch",
});
}
private ClassLoader getClassLoader() throws MalformedURLException {
return new URLClassLoader(new URL[] { new File(OUTPUT_PATH).toURI().toURL() }, getClass().getClassLoader());
}
@SuppressWarnings("unchecked")
private Callable getToast(ClassLoader classLoader, Method rye) throws ReflectiveOperationException {
Class toastClass = classLoader.loadClass("a.b.c.Toast$Toast");
return (Callable) box(toastClass
.getConstructor(Callable.class, Callable.class)
.newInstance(rye.invoke(null), box(4)));
}
private void shouldHaveClasses(String... classNames) throws MalformedURLException, ClassNotFoundException {
ClassLoader classLoader = getClassLoader();
for (String className : classNames) {
assertThat(classLoader.loadClass(className).getName(), is(className));
}
}
}