package jetbrains.mps.lang.test.runtime; /*Generated by MPS */ import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import java.awt.datatransfer.StringSelection; import jetbrains.mps.tool.environment.Environment; import org.jetbrains.annotations.NotNull; import jetbrains.mps.project.Project; import java.lang.reflect.InvocationTargetException; import org.jetbrains.mps.openapi.model.SModel; import jetbrains.mps.ide.ThreadUtils; import org.jetbrains.mps.openapi.module.SRepository; import org.jetbrains.mps.openapi.model.SModelReference; import org.jetbrains.mps.openapi.persistence.PersistenceFacade; import junit.framework.Assert; import jetbrains.mps.util.MacrosFactory; import java.io.File; import org.apache.log4j.Level; import jetbrains.mps.internal.collections.runtime.ListSequence; import jetbrains.mps.project.ProjectManager; import jetbrains.mps.baseLanguage.closures.runtime.Wrappers; import org.jetbrains.mps.openapi.module.SModule; import jetbrains.mps.module.ReloadableModule; import java.awt.GraphicsEnvironment; import java.awt.datatransfer.Clipboard; import java.awt.Toolkit; import jetbrains.mps.project.PathMacrosProvider; import java.util.Map; import jetbrains.mps.internal.collections.runtime.MapSequence; import java.util.HashMap; import jetbrains.mps.internal.collections.runtime.IMapping; import jetbrains.mps.core.tool.environment.util.CanonicalPath; import jetbrains.mps.core.tool.environment.util.MapPathMacrosProvider; import jetbrains.mps.project.PathMacros; public class TransformationTestRunner implements TestRunner { private static final Logger LOG = LogManager.getLogger(TransformationTestRunner.class); private static final String PATH_MACRO_PREFIX = "path.macro."; private static final StringSelection EMPTY_CLIPBOARD_CONTENT = new StringSelection(""); private final Environment myEnvironment; public TransformationTestRunner(@NotNull Environment environment) { myEnvironment = environment; } public void initTest(@NotNull final TransformationTest test, @NotNull String projectPath, String modelName) throws Exception { initTest(test, projectPath, modelName, false); } public void initTest(@NotNull final TransformationTest test, @NotNull String projectPath, String modelName, boolean reopenProject) throws Exception { clearSystemClipboard(); readSystemMacro(); final Project testProject = openTestProject(projectPath, reopenProject); doInitTest(test, testProject, modelName); myEnvironment.flushAllEvents(); } protected void doInitTest(@NotNull final TransformationTest test, @NotNull final Project testProject, final String modelName) throws InterruptedException, InvocationTargetException { if (LOG.isInfoEnabled()) { LOG.info("Initializing the test"); } test.setProject(testProject); TestModelSaver modelSaver = BaseTransformationTest.CACHE; TransformationTest cachedTest = modelSaver.getTest(); SModel cachedModel = check_ovzmet_a0f0l(cachedTest); SModel cachedTransientModel = check_ovzmet_a0g0l(cachedTest); String cachedModelName = check_ovzmet_a0h0l(check_ovzmet_a0a7a11(cachedModel)); if (cachedModelName != null && cachedModelName.equals(modelName)) { if (LOG.isDebugEnabled()) { LOG.debug("Using the cached model"); } test.setModelDescriptor(cachedModel); test.setTransientModelDescriptor(cachedTransientModel); } else { if (LOG.isDebugEnabled()) { LOG.debug("Recaching the model again"); } Exception exception = ThreadUtils.runInUIThreadAndWait(new Runnable() { public void run() { testProject.getModelAccess().executeCommand(new Runnable() { @Override public void run() { initialize(test, modelName); } private void initialize(final TransformationTest test, final String modelName) { SModel modelDescriptor = findModel(testProject.getRepository(), modelName); test.setModelDescriptor(modelDescriptor); test.init(); } }); } }); if (exception != null) { throw new RuntimeException(exception); } modelSaver.clean(); modelSaver.setTest(test); } } /*package*/ SModel findModel(SRepository repo, String modelName) { // method expects model read, otherwise why SModel as return value SModelReference modelRef = PersistenceFacade.getInstance().createModelReference(modelName); SModel modelDescriptor = modelRef.resolve(repo); if (modelDescriptor == null) { Assert.fail(String.format("Can't find model %s in supplied repository %s.", modelName, repo)); } return modelDescriptor; } protected Project openTestProject(String projectPathName, boolean reopenProject) { String expandedProjectPath = MacrosFactory.getGlobal().expandPath(projectPathName); File projectToOpen = new File(expandedProjectPath); if ((expandedProjectPath == null || expandedProjectPath.length() == 0)) { if (LOG.isEnabledFor(Level.WARN)) { LOG.warn("Project path is empty"); } Project openedProject = anyOpenedProject(); if (reopenProject) { openedProject.dispose(); } } else { if (reopenProject) { Project openedProject = myEnvironment.openProject(projectToOpen); openedProject.dispose(); } } return myEnvironment.openProject(projectToOpen); } /** * hacky place to run transformation tests with cached project */ private Project anyOpenedProject() { for (Project project : ListSequence.fromList(ProjectManager.getInstance().getOpenedProjects())) { if (project != null && !(project.isDisposed())) { return project; } } Assert.fail("MPS Project was not specified in the test class, no opened project was found."); return null; } public void runTest(@NotNull final TransformationTest projectTest, final String className, final String methodName, boolean runInCommand) throws Throwable { if (LOG.isInfoEnabled()) { LOG.info("Running the test " + methodName); } final Wrappers._T<Class> clazz = new Wrappers._T<Class>(); final Throwable[] error = new Throwable[1]; projectTest.getProject().getModelAccess().runReadAction(new Runnable() { public void run() { final SModule module = projectTest.getModelDescriptor().getModule(); if (!(module instanceof ReloadableModule)) { error[0] = new IllegalArgumentException("module" + module + " is not reloadable -- cannot run tests in it"); return; } try { clazz.value = ((ReloadableModule) module).getOwnClass(className); } catch (Throwable t) { error[0] = t; } } }); if (error[0] != null) { throw error[0]; } final Object obj = clazz.value.newInstance(); clazz.value.getField("myModel").set(obj, projectTest.getTransientModelDescriptor()); clazz.value.getField("myProject").set(obj, projectTest.getProject()); if (runInCommand) { ThreadUtils.runInUIThreadAndWait(new Runnable() { public void run() { projectTest.getProject().getModelAccess().executeCommand(new Runnable() { public void run() { error[0] = TransformationTestRunner.this.tryToRunTest(clazz.value, methodName, obj); } }); } }); myEnvironment.flushAllEvents(); } else { error[0] = TransformationTestRunner.this.tryToRunTest(clazz.value, methodName, obj); } if (error[0] != null) { if (LOG.isInfoEnabled()) { LOG.info("Test failed"); } throw error[0]; } if (LOG.isInfoEnabled()) { LOG.info("Test passed"); } } private static void clearSystemClipboard() { if (GraphicsEnvironment.isHeadless()) { return; } Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); clipboard.setContents(EMPTY_CLIPBOARD_CONTENT, EMPTY_CLIPBOARD_CONTENT); } /** * to enable such macros as ${charisma}; see MPS-10568 */ private static PathMacrosProvider readSystemMacro() { final Map<String, String> macros = MapSequence.fromMap(new HashMap<String, String>()); for (IMapping<Object, Object> property : MapSequence.fromMap(System.getProperties())) { if (property.key() instanceof String && property.value() instanceof String) { String key = (String) property.key(); String value = (String) property.value(); if ((key != null && key.length() > 0) && key.startsWith(PATH_MACRO_PREFIX)) { CanonicalPath path = new CanonicalPath(value); if (path.isValidDirectory()) { MapSequence.fromMap(macros).put(key.substring(PATH_MACRO_PREFIX.length()), path.getValue()); } } } } MapPathMacrosProvider provider = new MapPathMacrosProvider(macros); PathMacros.getInstance().addMacrosProvider(provider); return provider; } private Throwable tryToRunTest(Class clazz, String methodName, Object obj) { Throwable exception = null; try { clazz.getMethod(methodName).invoke(obj); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { exception = e.getTargetException(); } return exception; } private static SModel check_ovzmet_a0f0l(TransformationTest checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getModelDescriptor(); } return null; } private static SModel check_ovzmet_a0g0l(TransformationTest checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getTransientModelDescriptor(); } return null; } private static String check_ovzmet_a0h0l(SModelReference checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.toString(); } return null; } private static SModelReference check_ovzmet_a0a7a11(SModel checkedDotOperand) { if (null != checkedDotOperand) { return checkedDotOperand.getReference(); } return null; } }