diff --git a/java/execution/impl/src/com/intellij/testIntegration/RecentTestsData.java b/java/execution/impl/src/com/intellij/testIntegration/RecentTestsData.java new file mode 100644 index 000000000000..8b35d81bd91c --- /dev/null +++ b/java/execution/impl/src/com/intellij/testIntegration/RecentTestsData.java @@ -0,0 +1,222 @@ +/* + * 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.sm.runner.states.TestStateInfo; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +import static com.intellij.execution.testframework.sm.runner.states.TestStateInfo.Magnitude.*; +import static com.intellij.testIntegration.TestInfo.select; +import static com.intellij.testIntegration.TestInfo.selectNot; + +public class RecentTestsData { + private static Comparator TEST_BY_PATH_COMPARATOR = new Comparator() { + @Override + public int compare(SuiteInfo o1, SuiteInfo o2) { + String path1 = VirtualFileManager.extractPath(o1.getUrl()); + String path2 = VirtualFileManager.extractPath(o2.getUrl()); + return path1.compareTo(path2); + } + }; + + private final RecentTestRunner myRunner; + private final Map mySuites = ContainerUtil.newHashMap(); + + private List myTestsWithoutSuites = ContainerUtil.newArrayList(); + + public RecentTestsData(RecentTestRunner runner) { + myRunner = runner; + } + + public void addTest(String url, TestStateInfo.Magnitude magnitude) { + if (myRunner.isSuite(url)) { + mySuites.put(url, new SuiteInfo(url, magnitude)); + return; + } + + TestInfo testInfo = new TestInfo(url, magnitude); + + 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 calculateTestList() { + distributeUnmatchedTests(); + + List suites = ContainerUtil.newArrayList(mySuites.values()); + Collections.sort(suites, TEST_BY_PATH_COMPARATOR); + + List result = ContainerUtil.newArrayList(); + + fillWithSuites(result, select(suites, ERROR_INDEX)); + fillWithTests(result, select(myTestsWithoutSuites, ERROR_INDEX)); + + fillWithSuites(result, selectNot(suites, ERROR_INDEX, COMPLETE_INDEX, PASSED_INDEX)); + fillWithTests(result, selectNot(myTestsWithoutSuites, COMPLETE_INDEX, PASSED_INDEX)); + + fillWithSuites(result, select(suites, COMPLETE_INDEX, PASSED_INDEX)); + fillWithTests(result, select(myTestsWithoutSuites, COMPLETE_INDEX, PASSED_INDEX)); + + return result; + } + + private static void fillWithTests(List result, List tests) { + for (TestInfo info : tests) { + result.add(info.getUrl()); + } + } + + private static void fillWithSuites(List result, List suites) { + for (SuiteInfo suite : suites) { + result.addAll(suiteToTestList(suite)); + } + } + + private static List suiteToTestList(SuiteInfo suite) { + List result = ContainerUtil.newArrayList(); + + TestStateInfo.Magnitude suiteMagnitude = suite.getMagnitude(); + Set allTests = suite.getTests(); + + List sameMagnitudeTests = suite.getTests(suiteMagnitude); + if (sameMagnitudeTests.size() == allTests.size()) { + result.add(suite.getUrl()); + } + else { + result.add(suite.getUrl()); + for (TestInfo test : sameMagnitudeTests) { + result.add(test.getUrl()); + } + } + + return result; + } + + + private void distributeUnmatchedTests() { + List 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 tests = ContainerUtil.newHashSet(); + + public SuiteInfo(String url, TestStateInfo.Magnitude magnitude) { + super(url, magnitude); + mySuiteName = VirtualFileManager.extractPath(url); + } + + public String getSuiteName() { + return mySuiteName; + } + + public void addTest(TestInfo info) { + tests.add(info); + } + + public Set getTests() { + return tests; + } + + public List getTests(TestStateInfo.Magnitude magnitude) { + return select(tests, magnitude); + } +} + +class TestInfo { + private String url; + private TestStateInfo.Magnitude magnitude; + + public TestInfo(String url, TestStateInfo.Magnitude magnitude) { + this.url = url; + this.magnitude = magnitude; + } + + public String getUrl() { + return url; + } + + public TestStateInfo.Magnitude getMagnitude() { + return magnitude; + } + + public static List select(Collection infos, final TestStateInfo.Magnitude... magnitudes) { + return ContainerUtil.filter(infos, new Condition() { + @Override + public boolean value(T t) { + for (TestStateInfo.Magnitude magnitude : magnitudes) { + if (t.getMagnitude() == magnitude) { + return true; + } + } + return false; + } + }); + } + + public static List selectNot(Collection infos, final TestStateInfo.Magnitude... magnitudes) { + return ContainerUtil.filter(infos, new Condition() { + @Override + public boolean value(T t) { + for (TestStateInfo.Magnitude magnitude : magnitudes) { + if (t.getMagnitude() == magnitude) { + return false; + } + } + return true; + } + }); + } +} diff --git a/java/execution/impl/src/com/intellij/testIntegration/SelectTestStep.java b/java/execution/impl/src/com/intellij/testIntegration/SelectTestStep.java index 86634a11e095..2026b17ca0a5 100644 --- a/java/execution/impl/src/com/intellij/testIntegration/SelectTestStep.java +++ b/java/execution/impl/src/com/intellij/testIntegration/SelectTestStep.java @@ -22,11 +22,13 @@ import com.intellij.execution.testframework.sm.runner.states.TestStateInfo; import com.intellij.openapi.ui.popup.PopupStep; import com.intellij.openapi.ui.popup.util.BaseListPopupStep; import com.intellij.openapi.vfs.VirtualFileManager; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import java.util.*; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; public class SelectTestStep extends BaseListPopupStep { private static Comparator TEST_BY_PATH_COMPARATOR = new Comparator() { @@ -48,66 +50,15 @@ public class SelectTestStep extends BaseListPopupStep { } private static List getUrls(Map records, RecentTestRunner runner) { - TestGroup groups = toTestGroups(records, runner); - - List failed = ContainerUtil.newArrayList(groups.failedTests); - Collections.sort(failed, TEST_BY_PATH_COMPARATOR); - List other = ContainerUtil.newArrayList(groups.otherTests); - Collections.sort(other, TEST_BY_PATH_COMPARATOR); - List passed = ContainerUtil.newArrayList(groups.passedTests); - Collections.sort(passed, TEST_BY_PATH_COMPARATOR); - - failed.addAll(other); - failed.addAll(passed); - return failed; - } + RecentTestsData data = new RecentTestsData(runner); - private static TestGroup toTestGroups(Map records, RecentTestRunner runner) { - Set failedTests = ContainerUtil.newHashSet(); - Set passedSuites = ContainerUtil.newHashSet(); - Set otherSuites = ContainerUtil.newHashSet(); - - List infos = getTestInfos(records.entrySet(), runner); - - for (TestInfo info : infos) { - String url = info.url; - TestStateInfo.Magnitude magnitude = info.magnitude; - if (magnitude == null) continue; - - switch (magnitude) { - case COMPLETE_INDEX: - if (info.isSuite) { - passedSuites.add(url); - } - break; - case PASSED_INDEX: - if (info.isSuite) { - passedSuites.add(url); - } - break; - case ERROR_INDEX: - failedTests.add(url); - break; - default: - otherSuites.add(url); - break; - } - } - - return new TestGroup(failedTests, passedSuites, otherSuites); - } - - private static List getTestInfos(Set> entries, RecentTestRunner runner) { - List list = ContainerUtil.newSmartList(); - - for (Map.Entry item : entries) { - String url = item.getKey(); - TestStateStorage.Record record = item.getValue(); - TestStateInfo.Magnitude magnitude = getMagnitude(record.magnitude); - list.add(new TestInfo(url, magnitude, runner.isSuite(url))); + for (Map.Entry entry : records.entrySet()) { + String url = entry.getKey(); + TestStateStorage.Record record = entry.getValue(); + data.addTest(url, getMagnitude(record.magnitude)); } - return list; + return data.calculateTestList(); } private static TestStateInfo.Magnitude getMagnitude(int magnitude) { @@ -155,17 +106,4 @@ public class SelectTestStep extends BaseListPopupStep { this.otherTests = otherTests; } } - - private static class TestInfo { - private final boolean isSuite; - public String url; - public TestStateInfo.Magnitude magnitude; - - public TestInfo(String url, TestStateInfo.Magnitude magnitude, boolean isSuite) { - this.url = url; - this.magnitude = magnitude; - this.isSuite = isSuite; - } - } - } diff --git a/java/execution/impl/src/com/intellij/testIntegration/ShowRecentTests.java b/java/execution/impl/src/com/intellij/testIntegration/ShowRecentTests.java index 4834b82214bb..eb1a4d943d41 100644 --- a/java/execution/impl/src/com/intellij/testIntegration/ShowRecentTests.java +++ b/java/execution/impl/src/com/intellij/testIntegration/ShowRecentTests.java @@ -19,12 +19,12 @@ import com.intellij.execution.Location; import com.intellij.execution.TestStateStorage; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.ListPopupStep; import com.intellij.ui.popup.list.ListPopupImpl; import com.intellij.util.PsiNavigateUtil; import com.intellij.util.Time; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.event.ActionEvent; @@ -39,9 +39,14 @@ public class ShowRecentTests extends AnAction { return new Date(System.currentTimeMillis() - Time.DAY); } + @Override + public void update(@NotNull AnActionEvent e) { + e.getPresentation().setEnabled(e.getProject() != null); + } + @Override public void actionPerformed(AnActionEvent e) { - final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext()); + final Project project = e.getProject(); if (project == null) return; Map records = TestStateStorage.getInstance(project).getRecentTests(TEST_LIMIT, getSinceDate()); diff --git a/java/java-tests/testSrc/com/intellij/testIntergration/RecentTestsTest.kt b/java/java-tests/testSrc/com/intellij/testIntergration/RecentTestsTest.kt index 94c2350196ed..8f1965a7dc3b 100644 --- a/java/java-tests/testSrc/com/intellij/testIntergration/RecentTestsTest.kt +++ b/java/java-tests/testSrc/com/intellij/testIntergration/RecentTestsTest.kt @@ -67,6 +67,7 @@ class RecentTestsStepTest { map.put("java:suite://Test", passed) map.put("java:suite://JavaFormatterFailed", failed) map.put("java:test://JavaFormatterFailed.fail", failed) + map.put("java:test://JavaFormatterFailed.notFail", passed) map.put("java:test://Test.textYYY", passed) map.put("java:test://Test.textZZZ", passed) map.put("java:test://JavaFormatterSuperDuperTest.testFail", failed)