Commit 80b35b15 authored by Maksim Zuev's avatar Maksim Zuev Committed by intellij-monorepo-bot
Browse files

[coverage] IDEA-317736 Unify class/package coverage analysis

GitOrigin-RevId: 24c71b9ef489ec65dc7d995937bec487a29e2cc1
parent b90ea443
Branches unavailable Tags unavailable
No related merge requests found
Showing with 176 additions and 179 deletions
+176 -179
......@@ -129,8 +129,7 @@ public class JavaCoverageAnnotator extends BaseCoverageAnnotator implements Disp
Annotator annotator = new JavaPackageAnnotator();
long timeMs = TimeoutUtil.measureExecutionTime(() -> {
final int totalRoots = new JavaCoverageClassesEnumerator.RootsCounter(suite, project).getRoots();
new JavaCoverageClassesAnnotator(suite, project, annotator, totalRoots).visitSuite();
new JavaCoverageClassesAnnotator(suite, project, annotator).visitSuite();
myStructure = new CoverageClassStructure(project);
Disposer.register(this, myStructure);
dataManager.triggerPresentationUpdate();
......
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.coverage.analysis;
import com.intellij.coverage.CoverageSuite;
import com.intellij.coverage.CoverageSuitesBundle;
import com.intellij.coverage.JavaCoverageEngineExtension;
import com.intellij.coverage.JavaCoverageRunner;
import com.intellij.coverage.JavaCoverageSuite;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
......@@ -14,17 +14,16 @@ import com.intellij.openapi.roots.SourceFolder;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiPackage;
import com.intellij.rt.coverage.data.ProjectData;
import com.intellij.util.concurrency.AppExecutorUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import java.io.File;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
public class JavaCoverageClassesAnnotator extends JavaCoverageClassesEnumerator {
private static final Logger LOG = Logger.getInstance(JavaCoverageClassesAnnotator.class);
......@@ -40,14 +39,7 @@ public class JavaCoverageClassesAnnotator extends JavaCoverageClassesEnumerator
public JavaCoverageClassesAnnotator(@NotNull CoverageSuitesBundle suite,
@NotNull Project project,
@NotNull Annotator annotator) {
this(suite, project, annotator, 0);
}
public JavaCoverageClassesAnnotator(@NotNull CoverageSuitesBundle suite,
@NotNull Project project,
@NotNull Annotator annotator,
int totalRoots) {
super(suite, project, totalRoots);
super(suite, project);
myAnnotator = annotator;
myProjectData = mySuite.getCoverageData();
myPackageAnnotator = new PackageAnnotator(suite, project, myProjectData);
......@@ -55,18 +47,15 @@ public class JavaCoverageClassesAnnotator extends JavaCoverageClassesEnumerator
@Override
public void visitSuite() {
if (myProjectData == null) return;
myFlattenPackages.clear();
var created = initExecutor();
super.visitSuite();
if (created) stopExecutor();
collectPackageCoverage();
}
@Override
public void visitRootPackage(PsiPackage psiPackage, JavaCoverageSuite suite) {
if (myProjectData == null) return;
myFlattenPackages.clear();
var created = initExecutor();
super.visitRootPackage(psiPackage, suite);
private void collectPackageCoverage() {
final Map<String, PackageAnnotator.PackageCoverageInfo> packages = new HashMap<>();
for (Map.Entry<String, PackageAnnotator.AtomicPackageCoverageInfo> entry : myFlattenPackages.entrySet()) {
String packageFQName = AnalysisUtils.internalNameToFqn(entry.getKey());
......@@ -85,23 +74,22 @@ public class JavaCoverageClassesAnnotator extends JavaCoverageClassesEnumerator
for (Map.Entry<String, PackageAnnotator.PackageCoverageInfo> entry : packages.entrySet()) {
myAnnotator.annotatePackage(entry.getKey(), entry.getValue());
}
if (created) stopExecutor();
}
@Override
protected void visitSource(final PsiPackage psiPackage,
final Module module,
final String rootPackageVMName,
final boolean isTestSource,
final Set<VirtualFile> seenRoots) {
protected void visitSource(Module module, String rootPackageVMName, List<RequestRoot> roots) {
myFlattenDirectories.clear();
if (module.isDisposed()) {
LOG.warn("Module is already disposed: " + module);
return;
}
super.visitSource(psiPackage, module, rootPackageVMName, isTestSource, seenRoots);
final List<VirtualFile> sourceRoots = ContainerUtil.filter(prepareRoots(module, rootPackageVMName, isTestSource), Objects::nonNull);
super.visitSource(module, rootPackageVMName, roots);
syncPoolThreads();
collectDirectoryCoverage(module, rootPackageVMName);
}
private void collectDirectoryCoverage(Module module, String packageVMName) {
Set<VirtualFile> sourceRoots = prepareRoots(module, packageVMName);
final Map<VirtualFile, PackageAnnotator.DirCoverageInfo> directories = new HashMap<>();
for (Map.Entry<VirtualFile, PackageAnnotator.AtomicPackageCoverageInfo> entry : myFlattenDirectories.entrySet()) {
final PackageAnnotator.PackageCoverageInfo info = entry.getValue().toPackageCoverageInfo();
......@@ -123,15 +111,11 @@ public class JavaCoverageClassesAnnotator extends JavaCoverageClassesEnumerator
protected void visitClassFiles(final String toplevelClassSrcFQName,
final List<File> files,
final String packageVMName) {
if (JavaCoverageSuite.isClassFiltered(toplevelClassSrcFQName, myCurrentSuite.getExcludedClassNames())) return;
var runner = myCurrentSuite.getRunner();
boolean processUnloaded = runner instanceof JavaCoverageRunner && ((JavaCoverageRunner)runner).shouldProcessUnloadedClasses();
var children = new HashMap<String, File>();
for (File file : files) {
if (ignoreClass(file)) continue;
children.put(AnalysisUtils.getClassName(file), processUnloaded ? file : null);
}
if (isClassExcluded(toplevelClassSrcFQName)) return;
var children = files.stream()
.filter(Predicate.not(this::ignoreClass))
.collect(Collectors.toMap(AnalysisUtils::getClassName, Function.identity()));
if (children.isEmpty()) return;
myExecutor.execute(() -> {
PackageAnnotator.Result result = myPackageAnnotator.visitFiles(toplevelClassSrcFQName, children, packageVMName);
......@@ -141,19 +125,10 @@ public class JavaCoverageClassesAnnotator extends JavaCoverageClassesEnumerator
});
}
@Override
protected void visitClass(PsiClass psiClass) {
final String qualifiedName = psiClass.getQualifiedName();
final PackageAnnotator.ClassCoverageInfo info = myPackageAnnotator.visitClass(psiClass);
if (info != null && info.totalClassCount > 0) {
myAnnotator.annotateClass(qualifiedName, info);
}
}
private void annotateClass(String toplevelClassSrcFQName,
PackageAnnotator.ClassCoverageInfo info,
String packageVMName,
VirtualFile directory) {
PackageAnnotator.ClassCoverageInfo info,
String packageVMName,
VirtualFile directory) {
myAnnotator.annotateClass(toplevelClassSrcFQName, info);
getOrCreateFlattenPackage(packageVMName).append(info);
if (directory != null) {
......@@ -214,20 +189,29 @@ public class JavaCoverageClassesAnnotator extends JavaCoverageClassesEnumerator
return false;
}
private static VirtualFile[] prepareRoots(Module module, String rootPackageVMName, boolean isTestHierarchy) {
List<VirtualFile> result = new ArrayList<>();
private boolean isClassExcluded(String fqn) {
for (CoverageSuite suite : mySuite.getSuites()) {
if (suite instanceof JavaCoverageSuite javaSuite && JavaCoverageSuite.isClassFiltered(fqn, javaSuite.getExcludedClassNames())) {
return true;
}
}
return false;
}
private static Set<VirtualFile> prepareRoots(Module module, String rootPackageVMName) {
Set<VirtualFile> result = new HashSet<>();
final ContentEntry[] contentEntries = ModuleRootManager.getInstance(module).getContentEntries();
for (ContentEntry contentEntry : contentEntries) {
for (SourceFolder folder : contentEntry
.getSourceFolders(isTestHierarchy ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE)) {
for (SourceFolder folder : contentEntry.getSourceFolders()) {
final VirtualFile file = folder.getFile();
if (file == null) continue;
final String prefix = AnalysisUtils.fqnToInternalName(folder.getPackagePrefix());
final VirtualFile relativeSrcRoot = file.findFileByRelativePath(StringUtil.trimStart(rootPackageVMName, prefix));
if (relativeSrcRoot == null) continue;
result.add(relativeSrcRoot);
}
}
return result.toArray(VirtualFile.EMPTY_ARRAY);
return result;
}
private static int getWorkingThreads() {
......
......@@ -2,118 +2,61 @@
package com.intellij.coverage.analysis;
import com.intellij.coverage.CoverageDataManager;
import com.intellij.coverage.CoverageSuite;
import com.intellij.coverage.CoverageSuitesBundle;
import com.intellij.coverage.JavaCoverageSuite;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.OrderEnumerator;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassOwner;
import com.intellij.psi.PsiPackage;
import com.intellij.rt.coverage.data.ProjectData;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class JavaCoverageClassesEnumerator {
protected final CoverageSuitesBundle mySuite;
protected final Project myProject;
protected final CoverageDataManager myCoverageManager;
private final boolean[] myShouldVisitTestSource;
private final int myRootsCount;
private int myRootsCount;
private int myCurrentRootsCount;
protected JavaCoverageSuite myCurrentSuite;
public JavaCoverageClassesEnumerator(@NotNull final CoverageSuitesBundle suite, @NotNull final Project project, final int totalRoots) {
public JavaCoverageClassesEnumerator(@NotNull final CoverageSuitesBundle suite, @NotNull final Project project) {
mySuite = suite;
myProject = project;
myCoverageManager = CoverageDataManager.getInstance(myProject);
myShouldVisitTestSource = mySuite.isTrackTestFolders() ? new boolean[]{false, true} : new boolean[]{false};
myRootsCount = totalRoots;
}
protected void visitClass(PsiClass psiClass) { }
/**
* Visit classes with the same top level name.
*/
protected void visitClassFiles(String topLevelClassName, List<File> files, String packageVMName) { }
public void visitSuite() {
Map<ModuleRequest, List<RequestRoot>> roots = AnalyseKt.collectOutputRoots(mySuite, myProject);
myRootsCount = roots.values().stream().mapToInt(List::size).sum();
myCurrentRootsCount = 0;
updateProgress();
for (CoverageSuite coverageSuite : mySuite.getSuites()) {
JavaCoverageSuite javaSuite = (JavaCoverageSuite)coverageSuite;
final List<PsiClass> classes = javaSuite.getCurrentSuiteClasses(myProject);
final List<PsiPackage> packages = javaSuite.getCurrentSuitePackages(myProject);
for (PsiPackage psiPackage : packages) {
ProgressIndicatorProvider.checkCanceled();
visitRootPackage(psiPackage, javaSuite);
}
for (final PsiClass psiClass : classes) {
ProgressIndicatorProvider.checkCanceled();
ApplicationManager.getApplication().runReadAction(() -> {
final String packageName = ((PsiClassOwner)psiClass.getContainingFile()).getPackageName();
final PsiPackage psiPackage = JavaPsiFacade.getInstance(myProject).findPackage(packageName);
if (psiPackage == null) return;
visitClass(psiClass);
});
}
for (var e : roots.entrySet()) {
Module module = e.getKey().getModule();
String packageVMName = AnalysisUtils.fqnToInternalName(e.getKey().getPackageName());
visitSource(module, packageVMName, e.getValue());
}
}
//get read lock myself when needed
void visitRootPackage(final PsiPackage psiPackage, JavaCoverageSuite suite) {
myCurrentSuite = suite;
final ProjectData data = mySuite.getCoverageData();
if (data == null) return;
if (!isPackageFiltered(psiPackage)) return;
final Module[] modules = myCoverageManager.doInReadActionIfProjectOpen(() -> ModuleManager.getInstance(myProject).getModules());
if (modules == null) return;
final String rootPackageVMName = AnalysisUtils.fqnToInternalName(psiPackage.getQualifiedName());
final Set<VirtualFile> seenRoots = new HashSet<>();
for (final Module module : modules) {
if (!mySuite.getSearchScope(myProject).isSearchInModuleContent(module)) continue;
ProgressIndicatorProvider.checkCanceled();
for (boolean isTestSource : myShouldVisitTestSource) {
visitSource(psiPackage, module, rootPackageVMName, isTestSource, seenRoots);
}
protected void visitSource(Module module, String rootPackageVMName, List<RequestRoot> roots) {
for (RequestRoot request : roots) {
visitRoot(request.getRoot(), rootPackageVMName, request.getSimpleName());
}
}
protected void visitSource(final PsiPackage psiPackage,
final Module module,
final String rootPackageVMName,
final boolean isTestSource,
final Set<VirtualFile> seenRoots) {
final VirtualFile[] roots = getRoots(myCoverageManager, module, isTestSource);
for (VirtualFile output : roots) {
if (!seenRoots.add(output)) continue;
final File outputRoot = PackageAnnotator.findRelativeFile(rootPackageVMName, VfsUtilCore.virtualToIoFile(output));
if (outputRoot.exists()) {
visitRoot(outputRoot, rootPackageVMName);
}
}
}
protected void visitRoot(final File packageOutputRoot, final String rootPackageVMName) {
protected void visitRoot(File packageOutputRoot, String rootPackageVMName, @Nullable String requestedSimpleName) {
final Stack<PackageData> stack = new Stack<>(new PackageData(rootPackageVMName, packageOutputRoot.listFiles()));
while (!stack.isEmpty()) {
ProgressIndicatorProvider.checkCanceled();
......@@ -129,13 +72,17 @@ public abstract class JavaCoverageClassesEnumerator {
String toplevelClassSrcFQName = AnalysisUtils.getSourceToplevelFQName(classFqVMName);
topLevelClasses.computeIfAbsent(toplevelClassSrcFQName, k -> new ArrayList<>()).add(child);
}
else if (child.isDirectory()) {
else if (requestedSimpleName == null && child.isDirectory()) {
String childPackageVMName = AnalysisUtils.buildVMName(packageVMName, child.getName());
stack.push(new PackageData(childPackageVMName, child.listFiles()));
}
}
String requestedTopLevelName = requestedSimpleName == null ? null :
AnalysisUtils.internalNameToFqn(AnalysisUtils.buildVMName(packageVMName, requestedSimpleName));
for (Map.Entry<String, List<File>> entry : topLevelClasses.entrySet()) {
visitClassFiles(entry.getKey(), entry.getValue(), packageVMName);
String topLevelClassName = entry.getKey();
if (requestedTopLevelName != null && !requestedTopLevelName.equals(topLevelClassName)) continue;
visitClassFiles(topLevelClassName, entry.getValue(), packageVMName);
}
}
myCurrentRootsCount++;
......@@ -153,18 +100,9 @@ public abstract class JavaCoverageClassesEnumerator {
private record PackageData(String packageVMName, File[] children) {
}
private boolean isPackageFiltered(@NotNull PsiPackage psiPackage) {
final String qualifiedName = psiPackage.getQualifiedName();
for (CoverageSuite coverageSuite : mySuite.getSuites()) {
if (coverageSuite instanceof JavaCoverageSuite javaSuite && javaSuite.isPackageFiltered(qualifiedName)) {
return true;
}
}
return false;
}
/**
* Collect output roots for the specified module.
*
* @param includeTests if true, returns both production and test output roots; if false, returns only production roots
*/
public static VirtualFile @NotNull [] getRoots(final CoverageDataManager manager, final Module module, final boolean includeTests) {
......@@ -183,22 +121,4 @@ public abstract class JavaCoverageClassesEnumerator {
}
return files;
}
public static class RootsCounter extends JavaCoverageClassesEnumerator {
private int myRoots;
public RootsCounter(@NotNull CoverageSuitesBundle suite, @NotNull Project project) {
super(suite, project, 0);
visitSuite();
}
@Override
protected void visitRoot(File packageOutputRoot, String rootPackageVMName) {
myRoots++;
}
public int getRoots() {
return myRoots;
}
}
}
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.coverage.analysis
import com.intellij.coverage.CoverageDataManager
import com.intellij.coverage.CoverageSuitesBundle
import com.intellij.coverage.JavaCoverageSuite
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.VfsUtilCore
import java.io.File
internal fun collectOutputRoots(bundle: CoverageSuitesBundle, project: Project): Map<ModuleRequest, List<RequestRoot>> {
val coverageDataManager = CoverageDataManager.getInstance(project)
val javaSuites = bundle.suites.filterIsInstance<JavaCoverageSuite>()
val packageNames = javaSuites.flatMap { it.getCurrentSuitePackages(project).mapNotNull { p -> runReadAction { p.qualifiedName } } }
.removeSubPackages()
.filter { isPackageFiltered(bundle, it) }
val classes = javaSuites
.flatMap { it.getCurrentSuiteClasses(project) }.distinct()
.filter { aClass ->
val className = runReadAction { aClass.qualifiedName }
className != null && packageNames.none { className.startsWith(it) }
}
val modules = (if (packageNames.isNotEmpty()) {
coverageDataManager.doInReadActionIfProjectOpen { ModuleManager.getInstance(project).modules }?.toList() ?: emptyList()
}
else {
classes.mapNotNull { runReadAction { ModuleUtilCore.findModuleForPsiElement(it) } }.distinct()
})
.filter { bundle.getSearchScope(project).isSearchInModuleContent(it) }
val outputRoots = modules.flatMap { module ->
JavaCoverageClassesEnumerator.getRoots(coverageDataManager, module, bundle.isTrackTestFolders).toList().map { it to module }
}.distinct()
val requestedPackages = packageNames.map { it to null }
.plus(classes.mapNotNull { aClass ->
val fqn = runReadAction { aClass.qualifiedName }
fqn?.let { StringUtil.getPackageName(it) to StringUtil.getShortName(it) }
})
val roots = hashMapOf<ModuleRequest, MutableList<RequestRoot>>()
for ((root, module) in outputRoots) {
for ((packageName, simpleName) in requestedPackages) {
val packagePath = AnalysisUtils.fqnToInternalName(packageName)
val packageRoot = PackageAnnotator.findRelativeFile(packagePath, VfsUtilCore.virtualToIoFile(root))
if (packageRoot.exists()) {
roots.getOrPut(ModuleRequest(packageName, module)) { mutableListOf() }.add(RequestRoot(packageRoot, simpleName))
}
}
}
return roots
}
internal data class ModuleRequest(val packageName: String, val module: Module)
internal data class RequestRoot(val root: File, val simpleName: String?)
private fun List<String>.removeSubPackages(): List<String> {
val allPackages = this.sortedBy { it.length }
val packages = mutableListOf<String>()
for (fqn in allPackages) {
if (packages.none { it.startsWith(fqn) }) {
packages.add(fqn)
}
}
return packages
}
private fun isPackageFiltered(bundle: CoverageSuitesBundle, qualifiedName: String): Boolean {
for (coverageSuite in bundle.suites) {
if (coverageSuite is JavaCoverageSuite && coverageSuite.isPackageFiltered(qualifiedName)) {
return true
}
}
return false
}
......@@ -12,9 +12,7 @@ import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiPackage;
import com.intellij.rt.coverage.data.ClassData;
import com.intellij.rt.coverage.data.LineData;
import com.intellij.rt.coverage.data.ProjectData;
......@@ -64,7 +62,6 @@ public class CoverageAnnotatorIntegrationTest extends JavaModuleTestCase {
}
public void testExcludeEverythingFromCoverage() {
PsiPackage psiPackage = JavaPsiFacade.getInstance(getProject()).findPackage("p");
JavaCoverageEngine engine = new JavaCoverageEngine() {
@Override
public boolean acceptedByFilters(@NotNull PsiFile psiFile, @NotNull CoverageSuitesBundle suite) {
......@@ -88,7 +85,7 @@ public class CoverageAnnotatorIntegrationTest extends JavaModuleTestCase {
public void annotateClass(String classQualifiedName, PackageAnnotator.ClassCoverageInfo classCoverageInfo) {
Assert.fail("No classes are accepted by filter");
}
}).visitRootPackage(psiPackage, (JavaCoverageSuite)suite.getSuites()[0]);
}).visitSuite();
}
public void testMultipleSourceRoots() {
......@@ -111,7 +108,8 @@ public class CoverageAnnotatorIntegrationTest extends JavaModuleTestCase {
};
}
};
PsiPackage psiPackage = JavaPsiFacade.getInstance(getProject()).findPackage("p");
JavaCoverageSuite javaCoverageSuite = (JavaCoverageSuite)suite.getSuites()[0];
javaCoverageSuite.setIncludeFilters(new String[]{"p.*"});
Map<VirtualFile, PackageAnnotator.PackageCoverageInfo> dirs = new HashMap<>();
new JavaCoverageClassesAnnotator(suite, myProject, new Annotator() {
@Override
......@@ -119,7 +117,7 @@ public class CoverageAnnotatorIntegrationTest extends JavaModuleTestCase {
PackageAnnotator.PackageCoverageInfo packageCoverageInfo) {
dirs.put(virtualFile, packageCoverageInfo);
}
}).visitRootPackage(psiPackage, (JavaCoverageSuite)suite.getSuites()[0]);
}).visitSuite();
assertEquals(2, dirs.size());
for (PackageAnnotator.PackageCoverageInfo coverageInfo : dirs.values()) {
......
......@@ -8,8 +8,6 @@ import com.intellij.coverage.analysis.PackageAnnotator;
import com.intellij.idea.ExcludeFromTestDiscovery;
import com.intellij.openapi.application.PluginPathManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiPackage;
import com.intellij.rt.coverage.data.ClassData;
import com.intellij.rt.coverage.data.LineCoverage;
import com.intellij.testFramework.JavaModuleTestCase;
......@@ -33,11 +31,15 @@ public class CoverageIntegrationTest extends JavaModuleTestCase {
myProject = PlatformTestUtil.loadAndOpenProject(Paths.get(getTestDataPath()), getTestRootDisposable());
}
public void testIntegrationSimple() {
CoverageSuitesBundle bundle = loadCoverageSuite(IDEACoverageRunner.class, "simple$foo_in_simple.coverage", null);
CoverageDataManager.getInstance(myProject).chooseSuitesBundle(bundle);
}
public void testSimple() {
CoverageSuitesBundle bundle = loadCoverageSuite(IDEACoverageRunner.class, "simple$foo_in_simple.coverage");
PsiPackage psiPackage = JavaPsiFacade.getInstance(myProject).findPackage("foo");
CoverageSuitesBundle bundle = loadCoverageSuite(IDEACoverageRunner.class, "simple$foo_in_simple.coverage", null);
PackageAnnotationConsumer consumer = new PackageAnnotationConsumer();
new JavaCoverageClassesAnnotator(bundle, myProject, consumer).visitRootPackage(psiPackage, (JavaCoverageSuite)bundle.getSuites()[0]);
new JavaCoverageClassesAnnotator(bundle, myProject, consumer).visitSuite();
PackageAnnotator.ClassCoverageInfo barClassCoverage = consumer.myClassCoverageInfo.get("foo.bar.BarClass");
assertEquals(3, barClassCoverage.totalMethodCount);
assertEquals(1, barClassCoverage.coveredMethodCount);
......@@ -51,35 +53,48 @@ public class CoverageIntegrationTest extends JavaModuleTestCase {
assertEquals(0, uncoveredClassInfo.coveredMethodCount);
}
public void testSingleClassFilter() {
String[] filters = new String[]{"foo.bar.BarClass"};
CoverageSuitesBundle bundle = loadCoverageSuite(IDEACoverageRunner.class, "simple$foo_in_simple.coverage", filters);
PackageAnnotationConsumer consumer = new PackageAnnotationConsumer();
new JavaCoverageClassesAnnotator(bundle, myProject, consumer).visitSuite();
assertEquals(1, consumer.myClassCoverageInfo.size());
PackageAnnotator.ClassCoverageInfo barClassCoverage = consumer.myClassCoverageInfo.get("foo.bar.BarClass");
assertEquals(3, barClassCoverage.totalMethodCount);
assertEquals(1, barClassCoverage.coveredMethodCount);
}
public void testJaCoCo() {
CoverageSuitesBundle bundle = loadCoverageSuite(JaCoCoCoverageRunner.class, "simple$foo_in_simple.jacoco.coverage");
CoverageSuitesBundle bundle = loadCoverageSuite(JaCoCoCoverageRunner.class, "simple$foo_in_simple.jacoco.coverage", null);
ClassData classData = bundle.getCoverageData().getClassData("foo.FooClass");
// getStatus() never returns full coverage; it can only distinguish between none and partial
assertEquals(LineCoverage.PARTIAL, classData.getStatus("method1()I").intValue());
}
public void testHTMLReport() throws IOException {
CoverageSuitesBundle bundle = loadCoverageSuite(IDEACoverageRunner.class, "simple$foo_in_simple.coverage");
CoverageSuitesBundle bundle = loadCoverageSuite(IDEACoverageRunner.class, "simple$foo_in_simple.coverage", null);
File htmlDir = Files.createTempDirectory("html").toFile();
try {
ExportToHTMLSettings.getInstance(myProject).OUTPUT_DIRECTORY = htmlDir.getAbsolutePath();
new IDEACoverageRunner().generateReport(bundle, myProject);
assertTrue(htmlDir.exists());
assertTrue(new File(htmlDir, "index.html").exists());
} finally {
}
finally {
htmlDir.delete();
}
}
private CoverageSuitesBundle loadCoverageSuite(Class<? extends CoverageRunner> coverageRunnerClass, String coverageDataPath) {
private CoverageSuitesBundle loadCoverageSuite(Class<? extends CoverageRunner> coverageRunnerClass, String coverageDataPath,
String[] includeFilters) {
File coverageFile = new File(getTestDataPath(), coverageDataPath);
CoverageRunner runner = CoverageRunner.getInstance(coverageRunnerClass);
CoverageFileProvider fileProvider = new DefaultCoverageFileProvider(coverageFile);
CoverageSuite suite =
JavaCoverageEngine.getInstance().createCoverageSuite(runner, "Simple", fileProvider, null, -1, null, false, false, false, myProject);
CoverageSuitesBundle bundle = new CoverageSuitesBundle(suite);
CoverageDataManager.getInstance(myProject).chooseSuitesBundle(bundle);
return bundle;
CoverageSuite suite = JavaCoverageEngine.getInstance().createSuite(
runner, "Simple", fileProvider, includeFilters, null,
-1, false, false, false, myProject);
return new CoverageSuitesBundle(suite);
}
private static class PackageAnnotationConsumer implements Annotator {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment