mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
test discovery: module detection
(cherry picked from commit e538af4)
This commit is contained in:
+6
@@ -135,6 +135,12 @@ public abstract class TestDiscoveryConfiguration extends JavaTestConfigurationBa
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModule(Module module) {
|
||||
super.setModule(module);
|
||||
myDelegate.setModule(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeExternal(Element element) throws WriteExternalException {
|
||||
myDelegate.writeExternal(element);
|
||||
|
||||
+45
-10
@@ -18,12 +18,15 @@ package com.intellij.execution.testDiscovery;
|
||||
import com.intellij.codeInsight.TestFrameworks;
|
||||
import com.intellij.execution.JavaExecutionUtil;
|
||||
import com.intellij.execution.Location;
|
||||
import com.intellij.execution.RunnerAndConfigurationSettings;
|
||||
import com.intellij.execution.actions.ConfigurationContext;
|
||||
import com.intellij.execution.configurations.ConfigurationType;
|
||||
import com.intellij.execution.configurations.ModuleBasedConfiguration;
|
||||
import com.intellij.execution.junit.JavaRunConfigurationProducerBase;
|
||||
import com.intellij.execution.testframework.TestSearchScope;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
@@ -34,9 +37,13 @@ import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.testIntegration.TestFramework;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class TestDiscoveryConfigurationProducer extends JavaRunConfigurationProducerBase<TestDiscoveryConfiguration> {
|
||||
protected TestDiscoveryConfigurationProducer(ConfigurationType type) {
|
||||
@@ -57,18 +64,46 @@ public abstract class TestDiscoveryConfigurationProducer extends JavaRunConfigur
|
||||
final Pair<String, String> position = getPosition(location);
|
||||
if (position != null) {
|
||||
try {
|
||||
final Collection<String> testsByMethodName = TestDiscoveryIndex
|
||||
.getInstance(configuration.getProject()).getTestsByMethodName(position.first, position.second);
|
||||
if (testsByMethodName == null || ContainerUtil.filter(testsByMethodName, s -> s.startsWith(configuration.getFrameworkPrefix())).isEmpty()) return false;
|
||||
|
||||
final Project project = configuration.getProject();
|
||||
final TestDiscoveryIndex testDiscoveryIndex = TestDiscoveryIndex.getInstance(project);
|
||||
final Collection<String> testsByMethodName = testDiscoveryIndex.getTestsByMethodName(position.first, position.second);
|
||||
if (testsByMethodName == null ||
|
||||
ContainerUtil.filter(testsByMethodName, s -> s.startsWith(configuration.getFrameworkPrefix())).isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
configuration.setPosition(position);
|
||||
configuration.setName("Tests for " + StringUtil.getShortName(position.first) + "." + position.second);
|
||||
|
||||
final RunnerAndConfigurationSettings template =
|
||||
configurationContext.getRunManager().getConfigurationTemplate(getConfigurationFactory());
|
||||
final Module predefinedModule = ((ModuleBasedConfiguration)template.getConfiguration()).getConfigurationModule().getModule();
|
||||
if (predefinedModule != null) {
|
||||
configuration.setModule(predefinedModule);
|
||||
}
|
||||
|
||||
//potentially this set won't be big, it reflects modules from where user starts his tests
|
||||
final Collection<String> modules = testDiscoveryIndex.getTestModulesByMethodName(position.first, position.second);
|
||||
if (modules.isEmpty()) return true;
|
||||
|
||||
final ModuleManager moduleManager = ModuleManager.getInstance(project);
|
||||
final Set<Module> allModules = new HashSet<>(Arrays.asList(moduleManager.getModules()));
|
||||
modules.stream()
|
||||
.map(moduleManager::findModuleByName)
|
||||
.filter(module -> module != null)
|
||||
.forEach(module -> {
|
||||
final List<Module> dependentModules = ModuleUtilCore.getAllDependentModules(module);
|
||||
dependentModules.add(module);
|
||||
allModules.retainAll(dependentModules);
|
||||
});
|
||||
if (!allModules.isEmpty()) {
|
||||
configuration.setModule(allModules.iterator().next());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
configuration.setPosition(position);
|
||||
configuration.setName("Tests for " + StringUtil.getShortName(position.first) + "." + position.second);
|
||||
setupPackageConfiguration(configurationContext, configuration, TestSearchScope.MODULE_WITH_DEPENDENCIES);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+3
-3
@@ -46,7 +46,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -160,7 +159,7 @@ public class TestDiscoveryExtension extends RunConfigurationExtension {
|
||||
if (testMethodTraces != null) {
|
||||
for (File testMethodTrace : testMethodTraces) {
|
||||
try {
|
||||
coverageIndex.updateFromTestTrace(testMethodTrace);
|
||||
coverageIndex.updateFromTestTrace(testMethodTrace, ((JavaTestConfigurationBase)configuration).getConfigurationModule().getModule());
|
||||
FileUtil.delete(testMethodTrace);
|
||||
}
|
||||
catch (IOException e) {
|
||||
@@ -187,7 +186,8 @@ public class TestDiscoveryExtension extends RunConfigurationExtension {
|
||||
final File testMethodTrace = new File(tracesDirectory, className + "-" + methodName + ".tr");
|
||||
if (testMethodTrace.exists()) {
|
||||
try {
|
||||
coverageIndex.updateFromTestTrace(testMethodTrace);
|
||||
coverageIndex.updateFromTestTrace(testMethodTrace,
|
||||
((JavaTestConfigurationBase)configuration).getConfigurationModule().getModule());
|
||||
FileUtil.delete(testMethodTrace);
|
||||
}
|
||||
catch (IOException e) {
|
||||
|
||||
+64
-9
@@ -18,10 +18,12 @@ package com.intellij.execution.testDiscovery;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ProjectComponent;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.startup.StartupManager;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.newvfs.persistent.FlushingDaemon;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.io.*;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import gnu.trove.TIntHashSet;
|
||||
@@ -80,7 +82,9 @@ public class TestDiscoveryIndex implements ProjectComponent {
|
||||
|
||||
final int testNameId = holder.myTestNameEnumerator.tryEnumerate(testName);
|
||||
if (testNameId == 0) return;
|
||||
doUpdateFromDiff(holder, testNameId, null, holder.myTestNameToUsedClassesAndMethodMap.get(testNameId));
|
||||
doUpdateFromDiff(holder, testNameId, null,
|
||||
holder.myTestNameToUsedClassesAndMethodMap.get(testNameId),
|
||||
null);
|
||||
} catch (Throwable throwable) {
|
||||
thingsWentWrongLetsReinitialize(holder, throwable);
|
||||
}
|
||||
@@ -109,6 +113,31 @@ public class TestDiscoveryIndex implements ProjectComponent {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Collection<String> getTestModulesByMethodName(@NotNull String classFQName, @NotNull String methodName) throws IOException {
|
||||
synchronized (ourLock) {
|
||||
Holder holder = null;
|
||||
try {
|
||||
holder = getHolder();
|
||||
final TIntArrayList list = holder.myTestNameToNearestModule.get(
|
||||
createKey(
|
||||
holder.myClassEnumerator.enumerate(classFQName),
|
||||
holder.myMethodEnumerator.enumerate(methodName)
|
||||
)
|
||||
);
|
||||
if (list == null) return Collections.emptyList();
|
||||
final ArrayList<String> result = new ArrayList<String>(list.size());
|
||||
for (int moduleNameId : list.toNativeArray()) {
|
||||
result.add(holder.myModuleNameEnumerator.valueOf(moduleNameId));
|
||||
}
|
||||
return result;
|
||||
} catch (Throwable throwable) {
|
||||
thingsWentWrongLetsReinitialize(holder, throwable);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Holder getHolder() {
|
||||
Holder holder = myHolder;
|
||||
|
||||
@@ -154,17 +183,19 @@ public class TestDiscoveryIndex implements ProjectComponent {
|
||||
public void projectClosed() {
|
||||
}
|
||||
|
||||
private static final int VERSION = 2;
|
||||
private static final int VERSION = 3;
|
||||
|
||||
private final class Holder {
|
||||
final PersistentHashMap<Long, TIntArrayList> myMethodQNameToTestNames;
|
||||
final PersistentHashMap<Integer, TIntObjectHashMap<TIntArrayList>> myTestNameToUsedClassesAndMethodMap;
|
||||
final PersistentHashMap<Long, TIntArrayList> myTestNameToNearestModule;
|
||||
final PersistentStringEnumerator myClassEnumerator;
|
||||
final CachingEnumerator<String> myClassEnumeratorCache;
|
||||
final PersistentStringEnumerator myMethodEnumerator;
|
||||
final CachingEnumerator<String> myMethodEnumeratorCache;
|
||||
final PersistentStringEnumerator myTestNameEnumerator;
|
||||
final List<PersistentEnumeratorDelegate> myConstructedDataFiles = new ArrayList<PersistentEnumeratorDelegate>(4);
|
||||
final PersistentStringEnumerator myModuleNameEnumerator;
|
||||
final List<PersistentEnumeratorDelegate> myConstructedDataFiles = new ArrayList<PersistentEnumeratorDelegate>(6);
|
||||
|
||||
private ScheduledFuture<?> myFlushingFuture;
|
||||
private boolean myDisposed;
|
||||
@@ -178,6 +209,8 @@ public class TestDiscoveryIndex implements ProjectComponent {
|
||||
final File classNameEnumeratorFile = new File(path + File.separator + "classNameEnumerator.data");
|
||||
final File methodNameEnumeratorFile = new File(path + File.separator + "methodNameEnumerator.data");
|
||||
final File testNameEnumeratorFile = new File(path + File.separator + "testNameEnumerator.data");
|
||||
final File moduleNameEnumeratorFile = new File(path + File.separator + "moduleNameEnumerator.data");
|
||||
final File testNameToNearestModuleFile = new File(path + File.separator + "testNameToNearestModule.data");
|
||||
|
||||
try {
|
||||
int version = readVersion(versionFile);
|
||||
@@ -190,9 +223,11 @@ public class TestDiscoveryIndex implements ProjectComponent {
|
||||
|
||||
PersistentHashMap<Long, TIntArrayList> methodQNameToTestNames;
|
||||
PersistentHashMap<Integer, TIntObjectHashMap<TIntArrayList>> testNameToUsedClassesAndMethodMap;
|
||||
PersistentHashMap<Long, TIntArrayList> testNameToNearestModule;
|
||||
PersistentStringEnumerator classNameEnumerator;
|
||||
PersistentStringEnumerator methodNameEnumerator;
|
||||
PersistentStringEnumerator testNameEnumerator;
|
||||
PersistentStringEnumerator moduleNameEnumerator;
|
||||
|
||||
int iterations = 0;
|
||||
|
||||
@@ -214,12 +249,20 @@ public class TestDiscoveryIndex implements ProjectComponent {
|
||||
);
|
||||
myConstructedDataFiles.add(testNameToUsedClassesAndMethodMap);
|
||||
|
||||
testNameToNearestModule = new PersistentHashMap<Long, TIntArrayList>(testNameToNearestModuleFile,
|
||||
new MethodQNameSerializer(),
|
||||
new TestNamesExternalizer());
|
||||
myConstructedDataFiles.add(testNameToNearestModule);
|
||||
|
||||
classNameEnumerator = new PersistentStringEnumerator(classNameEnumeratorFile);
|
||||
myConstructedDataFiles.add(classNameEnumerator);
|
||||
|
||||
methodNameEnumerator = new PersistentStringEnumerator(methodNameEnumeratorFile);
|
||||
myConstructedDataFiles.add(methodNameEnumerator);
|
||||
|
||||
moduleNameEnumerator = new PersistentStringEnumerator(moduleNameEnumeratorFile);
|
||||
myConstructedDataFiles.add(methodNameEnumerator);
|
||||
|
||||
testNameEnumerator = new PersistentStringEnumerator(testNameEnumeratorFile);
|
||||
myConstructedDataFiles.add(testNameEnumerator);
|
||||
|
||||
@@ -242,9 +285,11 @@ public class TestDiscoveryIndex implements ProjectComponent {
|
||||
|
||||
myMethodQNameToTestNames = methodQNameToTestNames;
|
||||
myTestNameToUsedClassesAndMethodMap = testNameToUsedClassesAndMethodMap;
|
||||
myTestNameToNearestModule = testNameToNearestModule;
|
||||
myClassEnumerator = classNameEnumerator;
|
||||
myMethodEnumerator = methodNameEnumerator;
|
||||
myTestNameEnumerator = testNameEnumerator;
|
||||
myModuleNameEnumerator = moduleNameEnumerator;
|
||||
myMethodEnumeratorCache = new CachingEnumerator<String>(methodNameEnumerator, EnumeratorStringDescriptor.INSTANCE);
|
||||
myClassEnumeratorCache = new CachingEnumerator<String>(classNameEnumerator, EnumeratorStringDescriptor.INSTANCE);
|
||||
|
||||
@@ -416,14 +461,14 @@ public class TestDiscoveryIndex implements ProjectComponent {
|
||||
return val1.equals(val2);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateFromTestTrace(@NotNull File file) throws IOException {
|
||||
|
||||
public void updateFromTestTrace(@NotNull File file, @Nullable Module module) throws IOException {
|
||||
int fileNameDotIndex = file.getName().lastIndexOf('.');
|
||||
final String testName = fileNameDotIndex != -1 ? file.getName().substring(0, fileNameDotIndex) : file.getName();
|
||||
doUpdateFromTestTrace(file, testName);
|
||||
doUpdateFromTestTrace(file, testName, module);
|
||||
}
|
||||
|
||||
private void doUpdateFromTestTrace(File file, final String testName) throws IOException {
|
||||
private void doUpdateFromTestTrace(File file, final String testName, @Nullable Module module) throws IOException {
|
||||
synchronized (ourLock) {
|
||||
Holder holder = getHolder();
|
||||
if (holder.myDisposed) return;
|
||||
@@ -432,7 +477,7 @@ public class TestDiscoveryIndex implements ProjectComponent {
|
||||
TIntObjectHashMap<TIntArrayList> classData = loadClassAndMethodsMap(file, holder);
|
||||
TIntObjectHashMap<TIntArrayList> previousClassData = holder.myTestNameToUsedClassesAndMethodMap.get(testNameId);
|
||||
|
||||
doUpdateFromDiff(holder, testNameId, classData, previousClassData);
|
||||
doUpdateFromDiff(holder, testNameId, classData, previousClassData, module != null ? holder.myModuleNameEnumerator.enumerate(module.getName()) : null);
|
||||
} catch (Throwable throwable) {
|
||||
thingsWentWrongLetsReinitialize(holder, throwable);
|
||||
}
|
||||
@@ -442,7 +487,8 @@ public class TestDiscoveryIndex implements ProjectComponent {
|
||||
private void doUpdateFromDiff(Holder holder,
|
||||
final int testNameId,
|
||||
@Nullable TIntObjectHashMap<TIntArrayList> classData,
|
||||
@Nullable TIntObjectHashMap<TIntArrayList> previousClassData) throws IOException {
|
||||
@Nullable TIntObjectHashMap<TIntArrayList> previousClassData,
|
||||
@Nullable Integer moduleId) throws IOException {
|
||||
ValueDiff valueDiff = new ValueDiff(classData, previousClassData);
|
||||
|
||||
if (valueDiff.hasRemovedDelta()) {
|
||||
@@ -471,6 +517,15 @@ public class TestDiscoveryIndex implements ProjectComponent {
|
||||
DataInputOutputUtil.writeINT(dataOutput, testNameId);
|
||||
}
|
||||
});
|
||||
if (moduleId != null) {
|
||||
holder.myTestNameToNearestModule.appendData(createKey(classQName, methodName),
|
||||
new PersistentHashMap.ValueDataAppender() {
|
||||
@Override
|
||||
public void append(DataOutput dataOutput) throws IOException {
|
||||
DataInputOutputUtil.writeINT(dataOutput, moduleId);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user