/* * Copyright 2012-2014 Sergey Ignatov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.intellij.erlang.runconfig; import com.intellij.execution.Location; import com.intellij.execution.PsiLocation; import com.intellij.execution.actions.ConfigurationContext; import com.intellij.execution.actions.ConfigurationFromContext; import com.intellij.execution.actions.RunConfigurationProducer; import com.intellij.execution.configurations.RunConfiguration; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.util.Ref; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.testFramework.MapDataContext; import com.intellij.testFramework.ModuleTestCase; import com.intellij.testFramework.PsiTestUtil; import com.intellij.util.ArrayUtil; import org.intellij.erlang.application.ErlangApplicationRunConfigurationProducer; import org.intellij.erlang.eunit.ErlangUnitRunConfigurationProducer; import org.intellij.erlang.module.ErlangModuleType; import org.intellij.erlang.psi.ErlangFile; import org.intellij.erlang.psi.ErlangFunction; import org.intellij.erlang.utils.ErlangModulesUtil; import org.jetbrains.annotations.NotNull; public class ErlangDebuggableRunConfigurationProducerTest extends ModuleTestCase { @Override protected ModuleType getModuleType() { return ErlangModuleType.getInstance(); } @Override protected String getTestDirectoryName() { return "testData/runconfig/debuggableConfigurationProducer/"; } public void testNoNifs() throws Exception { Module noNifs = createErlangModule("no_nifs"); doTestDebugOptionsForSource(noNifs); doTestDebugOptionsForTests(noNifs); } public void testNifsInTests() throws Exception { Module nifsInTests = createErlangModule("nifs_in_tests"); doTestDebugOptionsForSource(nifsInTests); doTestDebugOptionsForTests(nifsInTests, "nifs_in_tests_test"); } public void testNifsInSource() throws Exception { Module nifsInSource = createErlangModule("nifs_in_source"); doTestDebugOptionsForSource(nifsInSource, "nifs_in_source"); doTestDebugOptionsForTests(nifsInSource, "nifs_in_source"); } public void testNoNifsDependentOnNifsInTests() throws Exception { Module noNifs = createErlangModule("no_nifs"); Module nifsInTests = createErlangModule("nifs_in_tests"); addDependency(noNifs, nifsInTests); doTestDebugOptionsForSource(noNifs); doTestDebugOptionsForTests(noNifs, "nifs_in_tests_test"); } public void testNoNifsDependentOnNifsInSource() throws Exception { Module noNifs = createErlangModule("no_nifs"); Module nifsInSource = createErlangModule("nifs_in_source"); addDependency(noNifs, nifsInSource); doTestDebugOptionsForSource(noNifs, "nifs_in_source"); doTestDebugOptionsForTests(noNifs, "nifs_in_source"); } public void testDependentNifsOfDependentModulesAreNotExcluded() throws Exception { Module noNifs = createErlangModule("no_nifs"); Module nifsInSource = createErlangModule("nifs_in_source"); Module nifsInTests = createErlangModule("nifs_in_tests"); addDependency(nifsInSource, noNifs); addDependency(nifsInTests, noNifs); doTestDebugOptionsForSource(noNifs); doTestDebugOptionsForTests(noNifs); } private void doTestDebugOptionsForSource(Module module, String... expectedModulesNotToInterpret) { doTestDebugOptions(ErlangApplicationRunConfigurationProducer.class, module, false, expectedModulesNotToInterpret); } private void doTestDebugOptionsForTests(Module module, String... expectedModulesNotToInterpret) { doTestDebugOptions(ErlangUnitRunConfigurationProducer.class, module, true, expectedModulesNotToInterpret); } private void doTestDebugOptions(Class<? extends ErlangDebuggableRunConfigurationProducer> producerClass, Module module, boolean useTestSource, String... expectedModulesNotToInterpret) { PsiElement elementToProduceFor = getElementToProduceFor(module, useTestSource); MapDataContext dataContext = new MapDataContext(); dataContext.put(CommonDataKeys.PROJECT, myProject); dataContext.put(LangDataKeys.MODULE, ModuleUtilCore.findModuleForPsiElement(elementToProduceFor)); dataContext.put(CommonDataKeys.PSI_ELEMENT, elementToProduceFor); dataContext.put(Location.DATA_KEY, PsiLocation.fromPsiElement(elementToProduceFor)); ConfigurationContext configurationContext = ConfigurationContext.getFromContext(dataContext); RunConfigurationProducer producer = RunConfigurationProducer.getInstance(producerClass); ConfigurationFromContext confFromCtx = producer.createConfigurationFromContext(configurationContext); assertNotNull(confFromCtx); RunConfiguration configuration = confFromCtx.getConfiguration(); assertNotNull(configuration); assertInstanceOf(configuration, ErlangRunConfigurationBase.class); @SuppressWarnings("unchecked") ErlangRunConfigurationBase c = (ErlangRunConfigurationBase) configuration; ErlangRunConfigurationBase.ErlangDebugOptions debugOptions = c.getDebugOptions(); assertTrue(debugOptions.isAutoUpdateModulesNotToInterpret()); assertSameElements(debugOptions.getModulesNotToInterpret(), expectedModulesNotToInterpret); } // We're producing for function named the same as it's containing module. // The containing module has the same name as it's IntelliJ's module and _test suffix if we're producing in test source. private PsiElement getElementToProduceFor(Module module, boolean useTestSource) { String erlangModuleName = module.getName() + (useTestSource ? "_test" : ""); GlobalSearchScope scope = GlobalSearchScope.moduleScope(module); ErlangFile erlangModule = ErlangModulesUtil.getErlangModuleFile(myProject, erlangModuleName, scope); ErlangFunction function = erlangModule != null ? erlangModule.getFunction(erlangModuleName, 0) : null; assertNotNull(function); return function; } @NotNull private Module createErlangModule(String moduleName) throws Exception { String dirInTestData = getTestDirectoryName() + moduleName; Module module = createModuleFromTestData(dirInTestData, moduleName, getModuleType(), false); ModuleRootManager rootManager = ModuleRootManager.getInstance(module); VirtualFile contentRoot = ArrayUtil.getFirstElement(rootManager.getContentRoots()); assertNotNull(contentRoot); VirtualFile sourceRoot = contentRoot.findChild("src"); if (sourceRoot != null) { PsiTestUtil.addSourceRoot(module, sourceRoot, false); } VirtualFile testRoot = contentRoot.findChild("test"); if (testRoot != null) { PsiTestUtil.addSourceRoot(module, testRoot, true); } return module; } private static void addDependency(final Module to, final Module what) throws Exception { final Ref<Exception> ex = Ref.create(); ApplicationManager.getApplication().runWriteAction(() -> { ModifiableRootModel modifiableModel = ModuleRootManager.getInstance(to).getModifiableModel(); try { modifiableModel.addModuleOrderEntry(what); modifiableModel.commit(); } catch (Exception e) { modifiableModel.dispose(); ex.set(e); } }); if (!ex.isNull()) { throw ex.get(); } } }