Recent tests collapses tests executed from the same run configuration.

- provided simple versioning of TestStateStorage.Record
- run configuration name hash is saved into TestStateStorage.Record
- lots of refactorings
This commit is contained in:
Yaroslav Lepenkin
2016-05-20 17:25:37 +03:00
parent b32e6aa73d
commit b6f14644b4
11 changed files with 531 additions and 683 deletions
@@ -136,6 +136,8 @@ public abstract class JavaTestFrameworkRunnableState<T extends
Disposer.register(getConfiguration().getProject(), consoleView);
final OSProcessHandler handler = createHandler(executor);
handler.putUserData(TestStateStorage.RUN_CONFIGURATION_NAME_KEY, getConfiguration().getName());
consoleView.attachToProcess(handler);
final AbstractTestProxy root = viewer.getRoot();
if (root instanceof TestProxyRoot) {
@@ -15,12 +15,19 @@
*/
package com.intellij.testIntegration;
import com.intellij.execution.Executor;
import com.intellij.execution.Location;
import com.intellij.execution.ProgramRunnerUtil;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface RecentTestRunner {
@@ -30,12 +37,16 @@ public interface RecentTestRunner {
}
void setMode(Mode mode);
void run(Location location);
void run(String url);
void run(RunnerAndConfigurationSettings configuration);
}
class RecentTestRunnerImpl implements RecentTestRunner {
private static AnAction RUN = ActionManager.getInstance().getAction("RunClass");
private static AnAction DEBUG = ActionManager.getInstance().getAction("DebugClass");
private final Project myProject;
private final TestLocator myTestLocator;
protected AnAction myCurrentAction = RUN;
@@ -50,7 +61,25 @@ class RecentTestRunnerImpl implements RecentTestRunner {
}
}
public void run(final Location location) {
public RecentTestRunnerImpl(Project project, TestLocator testLocator) {
myProject = project;
myTestLocator = testLocator;
}
@Override
public void run(RunnerAndConfigurationSettings configuration) {
Executor executor = myCurrentAction == RUN ? DefaultRunExecutor.getRunExecutorInstance()
: DefaultDebugExecutor.getDebugExecutorInstance();
ProgramRunnerUtil.executeConfiguration(myProject, configuration, executor);
}
public void run(@NotNull String url) {
Location location = myTestLocator.getLocation(url);
if (location == null) {
return;
}
DataContext data = new DataContext() {
@Nullable
@Override
@@ -0,0 +1,106 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* 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 com.intellij.testIntegration
import com.intellij.execution.RunnerAndConfigurationSettings
import com.intellij.execution.testframework.sm.runner.states.TestStateInfo
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.util.containers.ContainerUtil
import java.util.*
class RecentTestsData {
private val suitePacks = hashMapOf<String, SuitePackInfo>()
private var testsWithoutSuites: MutableList<TestInfo> = ContainerUtil.newArrayList<TestInfo>()
fun addSuite(url: String,
magnitude: TestStateInfo.Magnitude,
runDate: Date,
runConfiguration: RunnerAndConfigurationSettings)
{
val suiteInfo = SuiteInfo(url, magnitude, runDate, runConfiguration)
val suitePack = suitePacks[runConfiguration.uniqueID]
if (suitePack != null) {
suitePack.addSuite(suiteInfo)
return
}
suitePacks[runConfiguration.uniqueID] = SuitePackInfo(runConfiguration, suiteInfo)
}
fun addTest(url: String,
magnitude: TestStateInfo.Magnitude,
runDate: Date,
runConfiguration: RunnerAndConfigurationSettings) {
val testInfo = TestInfo(url, magnitude, runDate, runConfiguration)
val suite = findSuite(url, runConfiguration)
if (suite != null) {
suite.addTest(testInfo)
return
}
testsWithoutSuites.add(testInfo)
}
private fun findSuite(url: String, runConfiguration: RunnerAndConfigurationSettings): SuiteInfo? {
val pack: SuitePackInfo = suitePacks[runConfiguration.uniqueID] ?: return null
val testName = VirtualFileManager.extractPath(url)
pack.suites.forEach {
if (testName.startsWith(it.suiteName)) {
return it
}
}
return null
}
fun getTestsToShow(): List<RecentTestsPopupEntry> {
testsWithoutSuites.forEach {
val url = it.url
findSuite(url, it.runConfiguration)?.addTest(it)
}
val packsByDate = suitePacks.values.sortedByDescending { it.runDate }
return packsByDate.fold(listOf(), { list, pack -> list + pack.entriesToShow() })
}
}
fun SuitePackInfo.entriesToShow(): List<RecentTestsPopupEntry> {
if (suites.size == 1) {
return suites[0].entriesToShow()
}
val failedSuites = suites.filter { it.failedTests.size > 0 }
if (failedSuites.size == 0) {
return listOf(this)
}
return failedSuites + this
}
fun SuiteInfo.entriesToShow(): List<RecentTestsPopupEntry> {
val failed = failedTests
if (failed.size > 0) {
return failed.sortedByDescending { it.runDate } + this
}
return listOf(this)
}
@@ -15,42 +15,99 @@
*/
package com.intellij.testIntegration;
import com.intellij.execution.RunManagerEx;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.TestStateStorage;
import com.intellij.execution.configurations.ConfigurationType;
import com.intellij.execution.testframework.sm.runner.states.TestStateInfo;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.Function;
import com.intellij.openapi.project.Project;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.List;
import java.util.Map;
import static com.intellij.execution.testframework.sm.runner.states.TestStateInfo.Magnitude.*;
import static com.intellij.testIntegration.TestInfo.select;
import static com.intellij.execution.testframework.sm.runner.states.TestStateInfo.Magnitude.values;
interface ConfigurationByRecordProvider {
RunnerAndConfigurationSettings getConfiguration(TestStateStorage.Record record);
}
class RunConfigurationByRecordProvider implements ConfigurationByRecordProvider {
private final Project myProject;
private final Map<Integer, RunnerAndConfigurationSettings> myConfigurationsMap = ContainerUtil.newHashMap();
public RunConfigurationByRecordProvider(Project project) {
myProject = project;
initRunConfigurationsMap();
}
@Override
public RunnerAndConfigurationSettings getConfiguration(TestStateStorage.Record record) {
Integer runConfigurationHash = new Integer((int)record.configurationHash);
return myConfigurationsMap.get(runConfigurationHash);
}
private void initRunConfigurationsMap() {
RunManagerEx manager = RunManagerEx.getInstanceEx(myProject);
ConfigurationType[] types = manager.getConfigurationFactories();
for (ConfigurationType type : types) {
Map<String, List<RunnerAndConfigurationSettings>> structure = manager.getStructure(type);
for (Map.Entry<String, List<RunnerAndConfigurationSettings>> e : structure.entrySet()) {
for (RunnerAndConfigurationSettings settings : e.getValue()) {
myConfigurationsMap.put(settings.getName().hashCode(), settings);
}
}
}
}
}
public class RecentTestsListProvider {
private final Map<String, TestStateStorage.Record> myRecords;
private final ConfigurationByRecordProvider myConfigurationProvider;
public RecentTestsListProvider(Map<String, TestStateStorage.Record> records) {
myRecords = records;
public RecentTestsListProvider(ConfigurationByRecordProvider configurationProvider, Map<String, TestStateStorage.Record> records) {
myRecords = records;
myConfigurationProvider = configurationProvider;
}
public List<String> getUrlsToShowFromHistory() {
public List<RecentTestsPopupEntry> getTestsToShow() {
if (myRecords == null) return ContainerUtil.emptyList();
RecentTestsData data = new RecentTestsData();
for (Map.Entry<String, TestStateStorage.Record> entry : myRecords.entrySet()) {
String url = entry.getKey();
TestStateStorage.Record record = entry.getValue();
if (TestLocator.canLocate(url)) {
data.addTest(url, getMagnitude(record.magnitude), record.date);
handleUrl(data, url, record);
}
}
return data.getSortedTestsList();
return data.getTestsToShow();
}
private void handleUrl(RecentTestsData data, String url, TestStateStorage.Record record) {
TestStateInfo.Magnitude magnitude = getMagnitude(record.magnitude);
if (magnitude == null) {
return;
}
RunnerAndConfigurationSettings runConfiguration = myConfigurationProvider.getConfiguration(record);
if (TestLocator.isSuite(url)) {
if (runConfiguration != null) {
data.addSuite(url, magnitude, record.date, runConfiguration);
}
}
else {
data.addTest(url, magnitude, record.date, runConfiguration);
}
}
private static TestStateInfo.Magnitude getMagnitude(int magnitude) {
for (TestStateInfo.Magnitude m : values()) {
if (m.getValue() == magnitude) {
@@ -59,244 +116,4 @@ public class RecentTestsListProvider {
}
return null;
}
}
class RecentTestsData {
private static Comparator<TestInfo> BY_PATH_COMPARATOR = (o1, o2) -> {
String path1 = VirtualFileManager.extractPath(o1.getUrl());
String path2 = VirtualFileManager.extractPath(o2.getUrl());
return path1.compareTo(path2);
};
private static Comparator<SuiteInfo> SUITE_BY_RECENT_COMPARATOR =
(o1, o2) -> -o1.getMostRecentRunDate().compareTo(o2.getMostRecentRunDate());
private static Comparator<TestInfo> TEST_BY_RECENT_COMPARATOR = (o1, o2) -> -o1.getRunDate().compareTo(o2.getRunDate());
private final Map<String, SuiteInfo> mySuites = ContainerUtil.newHashMap();
private List<TestInfo> myTestsWithoutSuites = ContainerUtil.newArrayList();
public void addTest(String url, TestStateInfo.Magnitude magnitude, Date runDate) {
if (TestLocator.isSuite(url)) {
mySuites.put(url, new SuiteInfo(url, magnitude, runDate));
return;
}
TestInfo testInfo = new TestInfo(url, magnitude, runDate);
SuiteInfo suite = getSuite(url);
if (suite != null) {
suite.addTest(testInfo);
return;
}
myTestsWithoutSuites.add(testInfo);
}
@Nullable
private SuiteInfo getSuite(String url) {
String testName = VirtualFileManager.extractPath(url);
for (SuiteInfo info : mySuites.values()) {
String suiteName = info.getSuiteName();
if (testName.startsWith(suiteName)) {
return info;
}
}
return null;
}
public List<String> getSortedTestsList() {
distributeUnmatchedTests();
List<String> result = ContainerUtil.newArrayList();
fillWithTests(result, ERROR_INDEX, FAILED_INDEX);
fillWithTests(result, COMPLETE_INDEX, PASSED_INDEX, IGNORED_INDEX);
return result;
}
private void fillWithTests(List<String> result, TestStateInfo.Magnitude... magnitudes) {
List<SuiteInfo> suites = ContainerUtil.newArrayList(mySuites.values());
List<SuiteInfo> failedSuites = select(suites, magnitudes);
List<TestInfo> failedTests = select(myTestsWithoutSuites, magnitudes);
sortByPath(failedSuites);
sortByPath(failedTests);
sortSuitesByRecent(failedSuites);
sortTestsByRecent(failedTests);
fillWithSuites(result, failedSuites);
fillWithTests(result, failedTests);
}
private static void sortSuitesByRecent(List<SuiteInfo> suites) {
Collections.sort(suites, SUITE_BY_RECENT_COMPARATOR);
}
private static void sortTestsByRecent(List<TestInfo> tests) {
Collections.sort(tests, TEST_BY_RECENT_COMPARATOR);
}
private static void sortByPath(List<? extends TestInfo> list) {
Collections.sort(list, BY_PATH_COMPARATOR);
}
private static void fillWithTests(List<String> result, List<TestInfo> tests) {
for (TestInfo info : tests) {
result.add(info.getUrl());
}
}
private static void fillWithSuites(List<String> result, List<SuiteInfo> suites) {
for (SuiteInfo suite : suites) {
result.addAll(suiteToTestList(suite));
}
}
private static List<String> suiteToTestList(SuiteInfo suite) {
List<String> result = ContainerUtil.newArrayList();
if (suite.canTrustSuiteMagnitude() && suite.isPassed()) {
result.add(suite.getUrl());
return result;
}
List<TestInfo> failedTests = suite.getFailedTests();
sortTestsByRecent(failedTests);
if (failedTests.size() == suite.getTotalTestsCount()) {
result.add(suite.getUrl());
}
else if (failedTests.size() < 3) {
result.addAll(ContainerUtil.map(failedTests, testInfo -> {
return testInfo.getUrl();
}));
result.add(suite.getUrl());
}
else {
result.add(suite.getUrl());
result.addAll(ContainerUtil.map(failedTests, testInfo -> {
return testInfo.getUrl();
}));
}
return result;
}
private void distributeUnmatchedTests() {
List<TestInfo> noSuites = ContainerUtil.newSmartList();
for (TestInfo test : myTestsWithoutSuites) {
String url = test.getUrl();
SuiteInfo suite = getSuite(url);
if (suite != null) {
suite.addTest(test);
}
else {
noSuites.add(test);
}
}
myTestsWithoutSuites = noSuites;
}
}
class SuiteInfo extends TestInfo {
private final String mySuiteName;
private Set<TestInfo> tests = ContainerUtil.newHashSet();
public SuiteInfo(String url, TestStateInfo.Magnitude magnitude, Date runDate) {
super(url, magnitude, runDate);
mySuiteName = VirtualFileManager.extractPath(url);
}
public Date getMostRecentRunDate() {
Date mostRecent = getRunDate();
for (TestInfo test : tests) {
Date testDate = test.getRunDate();
if (testDate.compareTo(mostRecent) > 0) {
mostRecent = testDate;
}
}
return mostRecent;
}
public boolean canTrustSuiteMagnitude() {
Date suiteRunDate = getRunDate();
for (TestInfo test : tests) {
if (test.getRunDate().getTime() > suiteRunDate.getTime()) {
return false;
}
}
return true;
}
public boolean isPassed() {
return getMagnitude() == IGNORED_INDEX || getMagnitude() == PASSED_INDEX || getMagnitude() == COMPLETE_INDEX;
}
public List<TestInfo> getFailedTests() {
List<TestInfo> failed = ContainerUtil.newSmartList();
for (TestInfo test : tests) {
if (test.getMagnitude() == FAILED_INDEX || test.getMagnitude() == ERROR_INDEX) {
failed.add(test);
}
}
return failed;
}
public String getSuiteName() {
return mySuiteName;
}
public void addTest(TestInfo info) {
tests.add(info);
}
public int getTotalTestsCount() {
return tests.size();
}
}
class TestInfo {
private final Date runDate;
private final String url;
private final TestStateInfo.Magnitude magnitude;
public TestInfo(String url, TestStateInfo.Magnitude magnitude, Date runDate) {
this.url = url;
this.magnitude = magnitude;
this.runDate = runDate;
}
public Date getRunDate() {
return runDate;
}
public String getUrl() {
return url;
}
public TestStateInfo.Magnitude getMagnitude() {
return magnitude;
}
public static <T extends TestInfo> List<T> select(Collection<T> infos, final TestStateInfo.Magnitude... magnitudes) {
return ContainerUtil.filter(infos, new Condition<T>() {
@Override
public boolean value(T t) {
for (TestStateInfo.Magnitude magnitude : magnitudes) {
if (t.getMagnitude() == magnitude) {
return true;
}
}
return false;
}
});
}
}
}
@@ -1,62 +0,0 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* 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 com.intellij.testIntegration;
import com.intellij.execution.Location;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.vfs.VirtualFileManager;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.List;
import java.util.Map;
public class SelectTestStep extends BaseListPopupStep<String> {
private final RecentTestRunner myRunner;
private final TestLocator myTestLocator;
private final Map<String, Icon> myIcons;
public SelectTestStep(List<String> urls, Map<String, Icon> icons, RecentTestRunner runner, TestLocator locator) {
super("Debug Recent Tests", urls);
myRunner = runner;
myIcons = icons;
myTestLocator = locator;
}
@Override
public Icon getIconFor(String value) {
return myIcons.get(value);
}
@NotNull
@Override
public String getTextFor(String value) {
return VirtualFileManager.extractPath(value);
}
@Override
public boolean isSpeedSearchEnabled() {
return true;
}
@Override
public PopupStep onChosen(String url, boolean finalChoice) {
Location location = myTestLocator.getLocation(url);
myRunner.run(location);
return null;
}
}
@@ -0,0 +1,101 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* 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 com.intellij.testIntegration
import com.intellij.execution.testframework.TestIconMapper
import com.intellij.openapi.keymap.MacKeymapUtil
import com.intellij.openapi.ui.popup.ListPopupStep
import com.intellij.openapi.ui.popup.PopupStep
import com.intellij.openapi.ui.popup.util.BaseListPopupStep
import com.intellij.openapi.util.SystemInfo
import com.intellij.ui.popup.list.ListPopupImpl
import com.intellij.util.PsiNavigateUtil
import java.awt.event.ActionEvent
import java.awt.event.KeyEvent
import javax.swing.AbstractAction
import javax.swing.Icon
import javax.swing.KeyStroke
class RecentTestsListPopup(popupStep: ListPopupStep<RecentTestsPopupEntry>,
private val testRunner: RecentTestRunner,
private val locator: TestLocator)
: ListPopupImpl(popupStep)
{
init {
shiftReleased()
registerActions(this)
val shift = if (SystemInfo.isMac) MacKeymapUtil.SHIFT else "Shift"
setAdText("Debug with $shift, navigate with F4")
}
private fun registerActions(popup: ListPopupImpl) {
popup.registerAction("alternate", KeyStroke.getKeyStroke("shift pressed SHIFT"), object : AbstractAction() {
override fun actionPerformed(e: ActionEvent) = shiftPressed()
})
popup.registerAction("restoreDefault", KeyStroke.getKeyStroke("released SHIFT"), object : AbstractAction() {
override fun actionPerformed(e: ActionEvent) = shiftReleased()
})
popup.registerAction("invokeAction", KeyStroke.getKeyStroke("shift ENTER"), object : AbstractAction() {
override fun actionPerformed(e: ActionEvent) = handleSelect(true)
})
popup.registerAction("navigate", KeyStroke.getKeyStroke(KeyEvent.VK_F4, 0), object : AbstractAction() {
override fun actionPerformed(e: ActionEvent) {
val values = selectedValues
if (values.size == 1) {
val element = (values[0] as RecentTestsPopupEntry).navigatableElement(locator)
if (element != null) {
cancel()
PsiNavigateUtil.navigate(element)
}
}
}
})
}
private fun shiftPressed() {
setCaption("Debug Recent Tests")
testRunner.setMode(RecentTestRunner.Mode.DEBUG)
}
private fun shiftReleased() {
setCaption("Run Recent Tests")
testRunner.setMode(RecentTestRunner.Mode.RUN)
}
}
class SelectTestStep(tests: List<RecentTestsPopupEntry>,
private val runner: RecentTestRunner)
: BaseListPopupStep<RecentTestsPopupEntry>("Debug Recent Tests", tests)
{
override fun getIconFor(value: RecentTestsPopupEntry): Icon? {
return TestIconMapper.getIcon(value.magnitude)
}
override fun getTextFor(value: RecentTestsPopupEntry) = value.presentation
override fun isSpeedSearchEnabled() = true
override fun onChosen(entry: RecentTestsPopupEntry, finalChoice: Boolean): PopupStep<RecentTestsPopupEntry>? {
entry.run(runner)
return null
}
}
@@ -15,28 +15,15 @@
*/
package com.intellij.testIntegration;
import com.intellij.execution.Location;
import com.intellij.execution.TestStateStorage;
import com.intellij.execution.testframework.TestIconMapper;
import com.intellij.execution.testframework.sm.runner.states.TestStateInfo;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.keymap.MacKeymapUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.ListPopupStep;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.popup.list.ListPopupImpl;
import com.intellij.util.Function;
import com.intellij.util.PsiNavigateUtil;
import com.intellij.util.Time;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -60,88 +47,29 @@ public class ShowRecentTests extends AnAction {
final TestStateStorage testStorage = TestStateStorage.getInstance(project);
final TestLocator testLocator = new TestLocator(project);
final RecentTestRunnerImpl testRunner = new RecentTestRunnerImpl();
final RecentTestRunnerImpl testRunner = new RecentTestRunnerImpl(project, testLocator);
final Map<String, TestStateStorage.Record> records = testStorage.getRecentTests(TEST_LIMIT, getSinceDate());
RecentTestsListProvider listProvider = new RecentTestsListProvider(records);
List<String> urls = listProvider.getUrlsToShowFromHistory();
Map<String, Icon> icons = ContainerUtil.map2Map(urls, url -> {
return Pair.create(url, getIconFor(url, records));
});
SelectTestStep selectStepTest = new SelectTestStep(urls, icons, testRunner, testLocator);
RunConfigurationByRecordProvider configurationProvider = new RunConfigurationByRecordProvider(project);
RecentTestsListProvider listProvider = new RecentTestsListProvider(configurationProvider, records);
List<RecentTestsPopupEntry> entries = listProvider.getTestsToShow();
SelectTestStep selectStepTest = new SelectTestStep(entries, testRunner);
RecentTestsListPopup popup = new RecentTestsListPopup(selectStepTest, testRunner, testLocator);
popup.showCenteredInCurrentWindow(project);
cleanDeadTests(entries, testLocator, testStorage);
}
private static void cleanDeadTests(List<RecentTestsPopupEntry> entries, TestLocator testLocator, TestStateStorage testStorage) {
List<String> urls = ContainerUtil.newArrayList();
entries.forEach((entry) -> urls.addAll(entry.getTestsUrls()));
ApplicationManager.getApplication().executeOnPooledThread(new DeadTestsCleaner(testStorage, urls, testLocator));
}
private static Icon getIconFor(String value, Map<String, TestStateStorage.Record> records) {
TestStateStorage.Record record = records.get(value);
TestStateInfo.Magnitude magnitude = TestIconMapper.getMagnitude(record.magnitude);
return TestIconMapper.getIcon(magnitude);
}
}
class RecentTestsListPopup extends ListPopupImpl {
private final RecentTestRunner myTestRunner;
private final TestLocator myLocator;
public RecentTestsListPopup(ListPopupStep<String> popupStep, RecentTestRunner testRunner, TestLocator locator) {
super(popupStep);
myTestRunner = testRunner;
myLocator = locator;
shiftReleased();
registerActions(this);
String shift = SystemInfo.isMac ? MacKeymapUtil.SHIFT : "Shift";
setAdText("Debug with " + shift + ", navigate with F4");
}
private void registerActions(ListPopupImpl popup) {
popup.registerAction("alternate", KeyStroke.getKeyStroke("shift pressed SHIFT"), new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
shiftPressed();
}
});
popup.registerAction("restoreDefault", KeyStroke.getKeyStroke("released SHIFT"), new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
shiftReleased();
}
});
popup.registerAction("invokeAction", KeyStroke.getKeyStroke("shift ENTER"), new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
handleSelect(true);
}
});
popup.registerAction("navigate", KeyStroke.getKeyStroke(KeyEvent.VK_F4, 0), new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
Object[] values = getSelectedValues();
if (values.length == 1) {
Location location = myLocator.getLocation(values[0].toString());
if (location != null) {
cancel();
PsiNavigateUtil.navigate(location.getPsiElement());
}
}
}
});
}
private void shiftPressed() {
setCaption("Debug Recent Tests");
myTestRunner.setMode(RecentTestRunner.Mode.DEBUG);
}
private void shiftReleased() {
setCaption("Run Recent Tests");
myTestRunner.setMode(RecentTestRunner.Mode.RUN);
}
}
@@ -0,0 +1,98 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* 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 com.intellij.testIntegration
import com.intellij.execution.RunnerAndConfigurationSettings
import com.intellij.execution.testframework.sm.runner.states.TestStateInfo
import com.intellij.execution.testframework.sm.runner.states.TestStateInfo.Magnitude.*
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiElement
import com.intellij.util.containers.ContainerUtil
import java.util.*
interface RecentTestsPopupEntry {
val runDate: Date
val magnitude: TestStateInfo.Magnitude
val presentation: String
val testsUrls: List<String>
fun run(runner: RecentTestRunner)
open fun navigatableElement(locator: TestLocator): PsiElement? = null
}
open class TestInfo(val url: String,
override val magnitude: TestStateInfo.Magnitude,
override val runDate: Date,
val runConfiguration: RunnerAndConfigurationSettings) : RecentTestsPopupEntry
{
override val presentation = VirtualFileManager.extractPath(url)
override val testsUrls = listOf(url)
override fun run(runner: RecentTestRunner) {
runner.run(url)
}
override fun navigatableElement(locator: TestLocator) = locator.getLocation(url)?.psiElement
}
class SuiteInfo(url: String, magnitude: TestStateInfo.Magnitude, runDate: Date, runConfiguration: RunnerAndConfigurationSettings)
: TestInfo(url, magnitude, runDate, runConfiguration)
{
private val tests = hashSetOf<TestInfo>()
override val testsUrls: List<String>
get() = tests.fold(listOf<String>(), { acc, testEntry -> acc + testEntry.testsUrls })
val suiteName = VirtualFileManager.extractPath(url)
val failedTests: List<TestInfo>
get() = tests.filter { it.magnitude == FAILED_INDEX || it.magnitude == ERROR_INDEX }
fun addTest(info: TestInfo) = tests.add(info)
override val presentation = suiteName
}
class SuitePackInfo(val runSettings: RunnerAndConfigurationSettings, initial: SuiteInfo) : RecentTestsPopupEntry {
val suites = ContainerUtil.newArrayList<SuiteInfo>()
init {
addSuite(initial)
}
fun addSuite(s: SuiteInfo) = suites.add(s)
override val runDate = suites.map { it.runDate }.min()!!
override val magnitude = COMPLETE_INDEX
override val presentation = runSettings.name
override val testsUrls: List<String>
get() = suites.fold(listOf<String>(), { list, suite -> list + suite.testsUrls })
override fun run(runner: RecentTestRunner) {
runner.run(runSettings)
}
}