package com.netflix.nicobar.groovy2.plugin; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; import java.util.Collections; import org.testng.annotations.Test; import com.google.common.collect.Sets; import com.netflix.nicobar.core.archive.JarScriptArchive; import com.netflix.nicobar.core.archive.ModuleId; import com.netflix.nicobar.core.archive.PathScriptArchive; import com.netflix.nicobar.core.archive.ScriptArchive; import com.netflix.nicobar.core.archive.ScriptModuleSpec; import com.netflix.nicobar.core.module.ScriptModule; import com.netflix.nicobar.core.module.ScriptModuleLoader; import com.netflix.nicobar.core.module.ScriptModuleUtils; import com.netflix.nicobar.core.plugin.BytecodeLoadingPlugin; import com.netflix.nicobar.core.plugin.ScriptCompilerPluginSpec; import com.netflix.nicobar.groovy2.internal.compile.Groovy2Compiler; import com.netflix.nicobar.groovy2.testutil.GroovyTestResourceUtil; import com.netflix.nicobar.groovy2.testutil.GroovyTestResourceUtil.TestScript; /** * Unit tests for {@link ScriptModuleUtils} * * @author Vasanth Asokan */ public class ScriptModuleUtilsTest { private ScriptModuleLoader moduleLoader; /** * Convert a groovy based ScriptModule to a bytecode ScriptArchive * using {@link ScriptModuleUtils.toCompiledScriptArchive()} and * ensure that it works the same. * * @throws Exception */ @Test public void testScriptModuleConversion() throws Exception { Path scriptRootPath = GroovyTestResourceUtil.findRootPathForScript(TestScript.HELLO_WORLD); ScriptArchive scriptArchive = new PathScriptArchive.Builder(scriptRootPath) .setRecurseRoot(false) .addFile(TestScript.HELLO_WORLD.getScriptPath()) .setModuleSpec(createGroovyModuleSpec(TestScript.HELLO_WORLD.getModuleId()).build()) .build(); moduleLoader = createGroovyModuleLoader().build(); moduleLoader.updateScriptArchives(Collections.singleton(scriptArchive)); // locate the class file in the module and execute it ScriptModule scriptModule = moduleLoader.getScriptModule(TestScript.HELLO_WORLD.getModuleId()); assertNotNull(scriptModule); Path tmpDir = Files.createTempDirectory("ScriptModuleUtilsTest"); Path convertedJarPath = tmpDir.resolve("converted.jar"); ScriptModuleUtils.toCompiledScriptArchive(scriptModule, convertedJarPath, Sets.newHashSet(".class", ".groovy")); moduleLoader.removeScriptModule(ModuleId.create(TestScript.HELLO_WORLD.getModuleId())); // Now load the module again from the the converted jar archive JarScriptArchive convertedJarArchive = new JarScriptArchive.Builder(convertedJarPath).build(); moduleLoader.updateScriptArchives(Collections.singleton(convertedJarArchive)); scriptModule = moduleLoader.getScriptModule(TestScript.HELLO_WORLD.getModuleId()); assertNotNull(scriptModule); Class<?> targetClass = ScriptModuleUtils.findClass(scriptModule, "HelloWorld"); Object instance = targetClass.newInstance(); Method method = targetClass.getMethod("getMessage"); String message = (String)method.invoke(instance); assertEquals(message, "Hello, World!"); } private ScriptModuleLoader.Builder createGroovyModuleLoader() throws Exception { // create the groovy plugin spec. this plugin specified a new module and classloader called "Groovy2Runtime" // which contains the groovy-all-2.1.6.jar and the nicobar-groovy2 project. ScriptCompilerPluginSpec pluginSpec = new ScriptCompilerPluginSpec.Builder(Groovy2Compiler.GROOVY2_COMPILER_ID) .addRuntimeResource(GroovyTestResourceUtil.getGroovyRuntime()) .addRuntimeResource(GroovyTestResourceUtil.getGroovyPluginLocation()) // hack to make the gradle build work. still doesn't seem to properly instrument the code // should probably add a classloader dependency on the system classloader instead .addRuntimeResource(GroovyTestResourceUtil.getCoberturaJar(getClass().getClassLoader())) .withPluginClassName(Groovy2CompilerPlugin.class.getName()) .build(); // Create a compiler spec for the bytecode loading plugin ScriptCompilerPluginSpec bytecodeCompilerSpec = new ScriptCompilerPluginSpec.Builder(BytecodeLoadingPlugin.PLUGIN_ID) .withPluginClassName(BytecodeLoadingPlugin.class.getName()) .build(); // create and start the builder with the plugin return new ScriptModuleLoader.Builder().addPluginSpec(pluginSpec).addPluginSpec(bytecodeCompilerSpec); } /** * Create a module spec builder with pre-populated groovy dependency */ private ScriptModuleSpec.Builder createGroovyModuleSpec(String moduleId) { return new ScriptModuleSpec.Builder(moduleId) .addCompilerPluginId(Groovy2CompilerPlugin.PLUGIN_ID); } }