use test discovery in test data navigation

This commit is contained in:
Dmitry Batkovich
2018-09-27 18:49:31 +03:00
parent bf1448a73d
commit 2be6367da7
6 changed files with 94 additions and 15 deletions
@@ -7,8 +7,12 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.annotations.SerializedName;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.io.HttpRequests;
@@ -18,6 +22,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public class IntellijTestDiscoveryProducer implements TestDiscoveryProducer {
@@ -87,15 +92,27 @@ public class IntellijTestDiscoveryProducer implements TestDiscoveryProducer {
@NotNull
@Override
public List<String> getAffectedFilePaths(@NotNull Project project, @NotNull List<String> testFqns) throws IOException {
public List<String> getAffectedFilePaths(@NotNull Project project, @NotNull List<String> testFqns, byte frameworkId) throws IOException {
String url = INTELLIJ_TEST_DISCOVERY_HOST + "/search/test/details";
return HttpRequests.post(url, "application/json").productNameAsUserAgent().gzip(true).connect(r -> {
ThrowableComputable<List<String>, IOException> query = () -> HttpRequests.post(url, "application/json").productNameAsUserAgent().gzip(true).connect(r -> {
r.write(testFqns.stream().map(s -> "\"" + s + "\"").collect(Collectors.joining(",", "[", "]")));
return Arrays.stream(new ObjectMapper().readValue(r.getInputStream(), TestDetails[].class))
.map(details -> details.files)
.flatMap(Collection::stream)
.collect(Collectors.toList());
});
if (ApplicationManager.getApplication().isReadAccessAllowed()) {
List<String> result = ProgressManager.getInstance().run(new Task.WithResult<List<String>, IOException>(project,
"Searching for Affected File Paths...",
true) {
@Override
protected List<String> compute(@NotNull ProgressIndicator indicator) throws IOException {
return query.compute();
}
});
return result == null ? Collections.emptyList() : result;
}
return query.compute();
}
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@@ -6,7 +6,7 @@ import com.intellij.openapi.util.Couple;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
public class LocalTestDiscoveryProducer implements TestDiscoveryProducer {
@@ -36,8 +36,8 @@ public class LocalTestDiscoveryProducer implements TestDiscoveryProducer {
@NotNull
@Override
public List<String> getAffectedFilePaths(@NotNull Project project, @NotNull List<String> testFqns) throws IOException {
throw new UnsupportedOperationException();
public List<String> getAffectedFilePaths(@NotNull Project project, @NotNull List<String> testFqns, byte frameworkId) {
return Collections.emptyList();
}
@Override
@@ -67,12 +67,12 @@ public interface TestDiscoveryProducer {
}
@NotNull
List<String> getAffectedFilePaths(@NotNull Project project, @NotNull List<String> testFqns) throws IOException;
List<String> getAffectedFilePaths(@NotNull Project project, @NotNull List<String> testFqns, byte frameworkId) throws IOException;
//TODO use it [Dmitry Batkovich]
static void consumeAffectedPaths(@NotNull Project project, @NotNull List<String> testFqns, @NotNull Consumer<? super String> pathsConsumer) throws IOException {
// testFqn - className.methodName
static void consumeAffectedPaths(@NotNull Project project, @NotNull List<String> testFqns, @NotNull Consumer<? super String> pathsConsumer, byte frameworkId) throws IOException {
for (TestDiscoveryProducer extension : EP.getExtensions()) {
for (String path : extension.getAffectedFilePaths(project, testFqns)) {
for (String path : extension.getAffectedFilePaths(project, testFqns, frameworkId)) {
pathsConsumer.consume(path);
}
}
@@ -0,0 +1,61 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.idea.devkit.testAssistant;
import com.intellij.execution.testDiscovery.TestDiscoveryExtension;
import com.intellij.execution.testDiscovery.TestDiscoveryProducer;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestDataGuessByTestDiscoveryUtil {
public static final String COMMUNITY_PREFIX = "/community";
private static final Logger LOG = Logger.getInstance(TestDataGuessByTestDiscoveryUtil.class);
@NotNull
static List<String> collectTestDataByExistingFiles(@NotNull PsiMethod method) {
if (!(Registry.is(TestDiscoveryExtension.TEST_DISCOVERY_REGISTRY_KEY) || ApplicationManager.getApplication().isInternal())) {
return Collections.emptyList();
}
PsiClass testClass = method.getContainingClass();
if (testClass == null) return Collections.emptyList();
String testClassQualifiedName = testClass.getQualifiedName();
if (testClassQualifiedName == null) return Collections.emptyList();
List<String> testQName = Collections.singletonList(testClassQualifiedName + "." + method.getName());
try {
List<String> testData = new ArrayList<>();
Project project = method.getProject();
String basePath = project.getBasePath();
TestDiscoveryProducer.consumeAffectedPaths(project, testQName, path -> {
//TODO for those strange people with community sources
String fullPath = basePath + path;
if (FileUtil.exists(fullPath)) {
testData.add(fullPath);
return;
}
path = StringUtil.trimStart(path, COMMUNITY_PREFIX);
fullPath = basePath + path;
if (FileUtil.exists(fullPath)) {
testData.add(fullPath);
}
}, (byte)0x0 /* TODO */);
return testData;
}
catch (IOException e) {
LOG.error(e);
return Collections.emptyList();
}
}
}
@@ -61,12 +61,11 @@ public class TestDataNavigationHandler implements GutterIconNavigationHandler<Ps
}
if (collectByExistingFiles && (fileNames == null || fileNames.isEmpty())) {
fileNames = TestDataGuessByExistingFilesUtil.collectTestDataByExistingFiles(method);
fileNames = new ArrayList<>();
fileNames.addAll(TestDataGuessByExistingFilesUtil.collectTestDataByExistingFiles(method));
fileNames.addAll(TestDataGuessByTestDiscoveryUtil.collectTestDataByExistingFiles(method));
}
if (fileNames == null) {
fileNames = Collections.emptyList();
}
return fileNames;
return fileNames == null ? Collections.emptyList() : fileNames;
}
public static void navigate(@NotNull RelativePoint point,
@@ -53,7 +53,9 @@ public class TestDataReferenceCollector {
}
if (collectByExistingFiles && result.isEmpty()) {
result = TestDataGuessByExistingFilesUtil.collectTestDataByExistingFiles(method, myTestDataPath);
result = new ArrayList<>();
result.addAll(TestDataGuessByExistingFilesUtil.collectTestDataByExistingFiles(method, myTestDataPath));
result.addAll(TestDataGuessByTestDiscoveryUtil.collectTestDataByExistingFiles(method));
}
return result;
}