mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
refactor TestClassesFilter a bit closer to sanity
This commit is contained in:
@@ -55,68 +55,71 @@ public class TestClassesFilterTest extends TestCase {
|
||||
"com.intellij.package6.ExcludedTest\n" +
|
||||
"com.intellij.package7.*package8";
|
||||
|
||||
TestClassesFilter classesFilter = TestClassesFilter.createOn(new InputStreamReader(new ByteArrayInputStream(filterText.getBytes())));
|
||||
|
||||
String group1Name = "Group1";
|
||||
assertTrue(classesFilter.matches("com.intellij.package1.Test", group1Name));
|
||||
assertTrue(classesFilter.matches("com.intellij.package1.Test2", group1Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package2.Test", group1Name));
|
||||
assertTrue(classesFilter.matches("com.intellij.package2.ExcludedTest", group1Name));
|
||||
assertTrue(classesFilter.matches("com.intellij.package3.package4", group1Name));
|
||||
assertTrue(classesFilter.matches("com.intellij.package3.package5.package4", group1Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package3", group1Name));
|
||||
assertFalse(classesFilter.matches("com.intellij", group1Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.Test", group1Name));
|
||||
TestClassesFilter classesFilter = GroupBasedTestClassFilter
|
||||
.createOn(new InputStreamReader(new ByteArrayInputStream(filterText.getBytes())), "Group1");
|
||||
assertTrue(classesFilter.matches("com.intellij.package1.Test"));
|
||||
assertTrue(classesFilter.matches("com.intellij.package1.Test2"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package2.Test"));
|
||||
assertTrue(classesFilter.matches("com.intellij.package2.ExcludedTest"));
|
||||
assertTrue(classesFilter.matches("com.intellij.package3.package4"));
|
||||
assertTrue(classesFilter.matches("com.intellij.package3.package5.package4"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package3"));
|
||||
assertFalse(classesFilter.matches("com.intellij"));
|
||||
assertFalse(classesFilter.matches("com.intellij.Test"));
|
||||
|
||||
assertFalse(classesFilter.matches("com.intellij.package5.Test", group1Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package5.Test2", group1Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package6.Test", group1Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package6.ExcludedTest", group1Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package7.package8", group1Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package7.package5.package8", group1Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package7", group1Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package5.Test"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package5.Test2"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package6.Test"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package6.ExcludedTest"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package7.package8"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package7.package5.package8"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package7"));
|
||||
|
||||
String group2Name = "Group2";
|
||||
assertFalse(classesFilter.matches("com.intellij.package1.Test", group2Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package1.Test2", group2Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package2.Test", group2Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package2.ExcludedTest", group2Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package3.package4", group2Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package3.package5.package4", group2Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package3", group2Name));
|
||||
assertFalse(classesFilter.matches("com.intellij", group2Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.Test", group2Name));
|
||||
classesFilter = GroupBasedTestClassFilter
|
||||
.createOn(new InputStreamReader(new ByteArrayInputStream(filterText.getBytes())), "Group2");
|
||||
assertFalse(classesFilter.matches("com.intellij.package1.Test"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package1.Test2"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package2.Test"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package2.ExcludedTest"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package3.package4"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package3.package5.package4"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package3"));
|
||||
assertFalse(classesFilter.matches("com.intellij"));
|
||||
assertFalse(classesFilter.matches("com.intellij.Test"));
|
||||
|
||||
assertTrue(classesFilter.matches("com.intellij.package5.Test", group2Name));
|
||||
assertTrue(classesFilter.matches("com.intellij.package5.Test2", group2Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package6.Test", group2Name));
|
||||
assertTrue(classesFilter.matches("com.intellij.package6.ExcludedTest", group2Name));
|
||||
assertTrue(classesFilter.matches("com.intellij.package7.package8", group2Name));
|
||||
assertTrue(classesFilter.matches("com.intellij.package7.package5.package8", group2Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package7", group2Name));
|
||||
assertTrue(classesFilter.matches("com.intellij.package5.Test"));
|
||||
assertTrue(classesFilter.matches("com.intellij.package5.Test2"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package6.Test"));
|
||||
assertTrue(classesFilter.matches("com.intellij.package6.ExcludedTest"));
|
||||
assertTrue(classesFilter.matches("com.intellij.package7.package8"));
|
||||
assertTrue(classesFilter.matches("com.intellij.package7.package5.package8"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package7"));
|
||||
|
||||
checkForNullGroup(classesFilter, null);
|
||||
checkForNullGroup(classesFilter, TestClassesFilter.ALL_EXCLUDE_DEFINED);
|
||||
checkForNullGroup(filterText, null);
|
||||
checkForNullGroup(filterText, GroupBasedTestClassFilter.ALL_EXCLUDE_DEFINED);
|
||||
|
||||
}
|
||||
|
||||
private static void checkForNullGroup(TestClassesFilter classesFilter, String group0Name) {
|
||||
assertFalse(classesFilter.matches("com.intellij.package1.Test", group0Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package1.Test2", group0Name));
|
||||
assertTrue(classesFilter.matches("com.intellij.package2.Test", group0Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package2.ExcludedTest", group0Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package3.package4", group0Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package3.package5.package4", group0Name));
|
||||
assertTrue(classesFilter.matches("com.intellij.package3", group0Name));
|
||||
assertTrue(classesFilter.matches("com.intellij", group0Name));
|
||||
assertTrue(classesFilter.matches("com.intellij.Test", group0Name));
|
||||
private static void checkForNullGroup(String filterText, String group0Name) {
|
||||
TestClassesFilter classesFilter = GroupBasedTestClassFilter.createOn(new InputStreamReader(new ByteArrayInputStream(filterText.getBytes())), group0Name);
|
||||
|
||||
assertFalse(classesFilter.matches("com.intellij.package5.Test", group0Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package5.Test2", group0Name));
|
||||
assertTrue(classesFilter.matches("com.intellij.package6.Test", group0Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package6.ExcludedTest", group0Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package7.package8", group0Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package7.package5.package8", group0Name));
|
||||
assertTrue(classesFilter.matches("com.intellij.package7", group0Name));
|
||||
assertFalse(classesFilter.matches("com.intellij.package1.Test"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package1.Test2"));
|
||||
assertTrue(classesFilter.matches("com.intellij.package2.Test"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package2.ExcludedTest"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package3.package4"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package3.package5.package4"));
|
||||
assertTrue(classesFilter.matches("com.intellij.package3"));
|
||||
assertTrue(classesFilter.matches("com.intellij"));
|
||||
assertTrue(classesFilter.matches("com.intellij.Test"));
|
||||
|
||||
assertFalse(classesFilter.matches("com.intellij.package5.Test"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package5.Test2"));
|
||||
assertTrue(classesFilter.matches("com.intellij.package6.Test"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package6.ExcludedTest"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package7.package8"));
|
||||
assertFalse(classesFilter.matches("com.intellij.package7.package5.package8"));
|
||||
assertTrue(classesFilter.matches("com.intellij.package7"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Encapsulates logic of filtering test classes (classes that contain test-cases).
|
||||
* <p/>
|
||||
* We want to have such facility in order to be able to execute different sets of tests like <code>'fast tests'</code>,
|
||||
* <code>'problem tests'</code> etc.
|
||||
* <p/>
|
||||
* I.e. assumed usage scenario is to create object of this class with necessary filtering criteria and use it's
|
||||
* {@link #matches(String)} method for determining if particular test should be executed.
|
||||
* <p/>
|
||||
* The filtering is performed by fully-qualified test class name. There are two ways to define the criteria at the moment:
|
||||
* <ul>
|
||||
* <li>
|
||||
* Define target class name filters (at regexp format) explicitly using
|
||||
* {@link #TestClassesFilter(List) dedicated constructor};
|
||||
* </li>
|
||||
* <li>Read class name filters (at regexp format) from the given stream - see {@link #createOn(java.io.InputStreamReader, String)};</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class GroupBasedTestClassFilter extends TestClassesFilter {
|
||||
|
||||
private final Map<String, List<Pattern>> myPatterns = new HashMap<String, List<Pattern>>();
|
||||
|
||||
public static final ArrayList<Pattern> EMPTY_LIST = new ArrayList<Pattern>();
|
||||
private final List<Pattern> myAllPatterns = new ArrayList<Pattern>();
|
||||
private final List<Pattern> myTestGroupPatterns;
|
||||
|
||||
/**
|
||||
* Holds reserved test group name that serves as a negation of matching result.
|
||||
*
|
||||
* @see #matches(String)
|
||||
*/
|
||||
public static final String ALL_EXCLUDE_DEFINED = "ALL_EXCLUDE_DEFINED";
|
||||
private final String myTestGroupName;
|
||||
|
||||
private GroupBasedTestClassFilter(Map<String, List<String>> filters, String testGroupName) {
|
||||
myTestGroupName = testGroupName;
|
||||
|
||||
for (String groupName : filters.keySet()) {
|
||||
List<String> filterList = filters.get(groupName);
|
||||
addPatterns(groupName, filterList);
|
||||
}
|
||||
|
||||
myTestGroupPatterns = collectPatternsFor(myTestGroupName);
|
||||
}
|
||||
|
||||
private void addPatterns(String groupName, List<String> filterList) {
|
||||
ArrayList<Pattern> patterns = compilePatterns(filterList);
|
||||
myPatterns.put(groupName, patterns);
|
||||
myAllPatterns.addAll(patterns);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates <code>TestClassesFilter</code> object assuming that the given stream contains grouped test class filters
|
||||
* at the following format:
|
||||
* <p/>
|
||||
* <ul>
|
||||
* <li>
|
||||
* every line that starts with <code>'['</code> symbol and ends with <code>']'</code> symbol defines start
|
||||
* of the new test group. That means that all test class filters that follows this line belongs to the same
|
||||
* test group which name is defined by the text contained between <code>'['</code> and <code>']'</code>
|
||||
* </li>
|
||||
* <li>every line that is not a test-group definition is considered to be a test class filter at regexp format;</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* <b>Example</b>
|
||||
* Consider that given stream points to the following data:
|
||||
* <pre>
|
||||
* [CVS]
|
||||
* com.intellij.cvsSupport2.*
|
||||
* [STRESS_TESTS]
|
||||
* com.intellij.application.InspectionPerformanceTest
|
||||
* com.intellij.application.TraverseUITest
|
||||
* </pre>
|
||||
* <p/>
|
||||
* It defines two test groups:
|
||||
* <ul>
|
||||
* <li><b>CVS</b> group with the single test class name pattern <code>'com.intellij.cvsSupport2.*'</code>;</li>
|
||||
* <li>
|
||||
* <b>STRESS_TESTS</b> group with the following test class name patterns:
|
||||
* <ul>
|
||||
* <li>com.intellij.application.InspectionPerformanceTest</li>
|
||||
* <li>com.intellij.application.TraverseUITest</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* This method doesn't suppose itself to be owner of the given stream reader, i.e. it assumes that the stream should be
|
||||
* closed on caller side.
|
||||
*
|
||||
*
|
||||
* @param inputStreamReader reader that points to the target test groups config
|
||||
* @param testGroupName
|
||||
* @return newly created {@link GroupBasedTestClassFilter} object with the data contained at the given reader
|
||||
* @see #matches(String)
|
||||
*/
|
||||
@SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"})
|
||||
public static TestClassesFilter createOn(InputStreamReader inputStreamReader, String testGroupName) {
|
||||
try {
|
||||
Map<String, List<String>> groupNameToPatternsMap = new HashMap<String, List<String>>();
|
||||
String currentGroupName = "";
|
||||
LineNumberReader lineNumberReader = new LineNumberReader(inputStreamReader);
|
||||
String line;
|
||||
while ((line = lineNumberReader.readLine()) != null) {
|
||||
if (line.startsWith("#")) continue;
|
||||
if (line.startsWith("[") && line.endsWith("]")) {
|
||||
currentGroupName = line.substring(1, line.length() - 1);
|
||||
}
|
||||
else {
|
||||
if (!groupNameToPatternsMap.containsKey(currentGroupName)) {
|
||||
groupNameToPatternsMap.put(currentGroupName, new ArrayList<String>());
|
||||
}
|
||||
groupNameToPatternsMap.get(currentGroupName).add(line);
|
||||
}
|
||||
}
|
||||
|
||||
return new GroupBasedTestClassFilter(groupNameToPatternsMap, testGroupName);
|
||||
}
|
||||
catch (IOException e) {
|
||||
return ALL_CLASSES;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to check if given class name belongs to the test group with the given name based on filtering rules encapsulated
|
||||
* at the current {@link GroupBasedTestClassFilter} object. I.e. this method returns <code>true</code> if given test class name
|
||||
* is matched with any test class name filter configured for the test group with the given name.
|
||||
* <p/>
|
||||
* <b>Note:</b> there is a special case processing when given group name is {@link #ALL_EXCLUDE_DEFINED}. This method
|
||||
* returns <code>true</code> only if all registered patterns (for all test groups) don't match given test class name.
|
||||
*
|
||||
* @param className target test class name to check
|
||||
* @return <code>true</code> if given test group name is defined (not <code>null</code>) and test class with given
|
||||
* name belongs to the test group with given name;
|
||||
* <code>true</code> if given group if undefined or equal to {@link #ALL_EXCLUDE_DEFINED} and given test
|
||||
* class name is not matched by all registered patterns;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(String className) {
|
||||
boolean result = matchesAnyPattern(myTestGroupPatterns, className);
|
||||
//null group means all patterns from each defined group should be excluded
|
||||
if (isAllExcludeDefinedGroup(myTestGroupName)) {
|
||||
return !result;
|
||||
}
|
||||
else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isAllExcludeDefinedGroup(String groupName) {
|
||||
return StringUtil.isEmpty(groupName) || ALL_EXCLUDE_DEFINED.equalsIgnoreCase(groupName.trim());
|
||||
}
|
||||
|
||||
private List<Pattern> collectPatternsFor(String groupName) {
|
||||
if (isAllExcludeDefinedGroup(groupName)){
|
||||
return myAllPatterns;
|
||||
} else {
|
||||
if (!myPatterns.containsKey(groupName)){
|
||||
return EMPTY_LIST;
|
||||
} else {
|
||||
return myPatterns.get(groupName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2011 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;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PatternListTestClassFilter extends TestClassesFilter {
|
||||
private final List<Pattern> myPatterns;
|
||||
|
||||
public PatternListTestClassFilter(List<String> patterns) {
|
||||
myPatterns = compilePatterns(patterns);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(String className) {
|
||||
return TestClassesFilter.matchesAnyPattern(myPatterns, className);
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ public class TestCaseLoader {
|
||||
}
|
||||
if (excludedStream != null) {
|
||||
try {
|
||||
myTestClassesFilter = TestClassesFilter.createOn(new InputStreamReader(excludedStream));
|
||||
myTestClassesFilter = GroupBasedTestClassFilter.createOn(new InputStreamReader(excludedStream), myTestGroupName);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
@@ -83,10 +83,10 @@ public class TestCaseLoader {
|
||||
else {
|
||||
String patterns = System.getProperty(TARGET_TEST_PATTERNS);
|
||||
if (patterns != null) {
|
||||
myTestClassesFilter = new TestClassesFilter(StringUtil.split(patterns, ";"));
|
||||
myTestClassesFilter = new PatternListTestClassFilter(StringUtil.split(patterns, ";"));
|
||||
}
|
||||
else {
|
||||
myTestClassesFilter = TestClassesFilter.EMPTY_CLASSES_FILTER;
|
||||
myTestClassesFilter = TestClassesFilter.ALL_CLASSES;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ public class TestCaseLoader {
|
||||
* Determine if we should exclude this test case.
|
||||
*/
|
||||
private boolean shouldExcludeTestClass(Class testCaseClass) {
|
||||
return !myTestClassesFilter.matches(testCaseClass.getName(), myTestGroupName) || isBombed(testCaseClass)
|
||||
return !myTestClassesFilter.matches(testCaseClass.getName()) || isBombed(testCaseClass)
|
||||
|| blockedTests.contains(testCaseClass.getName());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2011 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.
|
||||
@@ -15,146 +15,37 @@
|
||||
*/
|
||||
package com.intellij;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Encapsulates logic of filtering test classes (classes that contain test-cases).
|
||||
* <p/>
|
||||
* We want to have such facility in order to be able to execute different sets of tests like <code>'fast tests'</code>,
|
||||
* <code>'problem tests'</code> etc.
|
||||
* <p/>
|
||||
* I.e. assumed usage scenario is to create object of this class with necessary filtering criteria and use it's
|
||||
* {@link #matches(String, String)} method for determining if particular test should be executed.
|
||||
* <p/>
|
||||
* The filtering is performed by fully-qualified test class name. There are two ways to define the criteria at the moment:
|
||||
* <ul>
|
||||
* <li>
|
||||
* Define target class name filters (at regexp format) explicitly using
|
||||
* {@link #TestClassesFilter(List) dedicated constructor};
|
||||
* </li>
|
||||
* <li>Read class name filters (at regexp format) from the given stream - see {@link #createOn(InputStreamReader)};</li>
|
||||
* </ul>
|
||||
* @author yole
|
||||
*/
|
||||
public class TestClassesFilter {
|
||||
|
||||
private final Map<String, List<Pattern>> myPatterns = new HashMap<String, List<Pattern>>();
|
||||
public static final TestClassesFilter EMPTY_CLASSES_FILTER = new TestClassesFilter(new HashMap<String, List<String>>());
|
||||
public static final ArrayList<Pattern> EMPTY_LIST = new ArrayList<Pattern>();
|
||||
private final List<Pattern> myAllPatterns = new ArrayList<Pattern>();
|
||||
|
||||
/**
|
||||
* Holds reserved test group name that serves as a negation of matching result.
|
||||
*
|
||||
* @see #matches(String, String)
|
||||
*/
|
||||
public static final String ALL_EXCLUDE_DEFINED = "ALL_EXCLUDE_DEFINED";
|
||||
|
||||
private TestClassesFilter(Map<String, List<String>> filters) {
|
||||
|
||||
for (String groupName : filters.keySet()) {
|
||||
List<String> filterList = filters.get(groupName);
|
||||
addPatterns(groupName, filterList);
|
||||
public abstract class TestClassesFilter {
|
||||
public static final TestClassesFilter ALL_CLASSES = new TestClassesFilter() {
|
||||
@Override
|
||||
public boolean matches(String className) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates new <code>TestClassesFilter</code> object with the given list of matching patterns (at regexp format).
|
||||
*
|
||||
* @param filterList list of test class matching patterns
|
||||
*/
|
||||
TestClassesFilter(List<String> filterList) {
|
||||
addPatterns("", filterList);
|
||||
}
|
||||
public abstract boolean matches(String className);
|
||||
|
||||
private void addPatterns(String groupName, List<String> filterList) {
|
||||
protected static ArrayList<Pattern> compilePatterns(List<String> filterList) {
|
||||
ArrayList<Pattern> patterns = new ArrayList<Pattern>();
|
||||
myPatterns.put(groupName, patterns);
|
||||
for (String aFilter : filterList) {
|
||||
String filter = aFilter.trim();
|
||||
if (filter.length() == 0) continue;
|
||||
filter = filter.replaceAll("\\*", ".\\*");
|
||||
Pattern pattern = Pattern.compile(filter);
|
||||
myAllPatterns.add(pattern);
|
||||
patterns.add(pattern);
|
||||
}
|
||||
return patterns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates <code>TestClassesFilter</code> object assuming that the given stream contains grouped test class filters
|
||||
* at the following format:
|
||||
* <p/>
|
||||
* <ul>
|
||||
* <li>
|
||||
* every line that starts with <code>'['</code> symbol and ends with <code>']'</code> symbol defines start
|
||||
* of the new test group. That means that all test class filters that follows this line belongs to the same
|
||||
* test group which name is defined by the text contained between <code>'['</code> and <code>']'</code>
|
||||
* </li>
|
||||
* <li>every line that is not a test-group definition is considered to be a test class filter at regexp format;</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* <b>Example</b>
|
||||
* Consider that given stream points to the following data:
|
||||
* <pre>
|
||||
* [CVS]
|
||||
* com.intellij.cvsSupport2.*
|
||||
* [STRESS_TESTS]
|
||||
* com.intellij.application.InspectionPerformanceTest
|
||||
* com.intellij.application.TraverseUITest
|
||||
* </pre>
|
||||
* <p/>
|
||||
* It defines two test groups:
|
||||
* <ul>
|
||||
* <li><b>CVS</b> group with the single test class name pattern <code>'com.intellij.cvsSupport2.*'</code>;</li>
|
||||
* <li>
|
||||
* <b>STRESS_TESTS</b> group with the following test class name patterns:
|
||||
* <ul>
|
||||
* <li>com.intellij.application.InspectionPerformanceTest</li>
|
||||
* <li>com.intellij.application.TraverseUITest</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* This method doesn't suppose itself to be owner of the given stream reader, i.e. it assumes that the stream should be
|
||||
* closed on caller side.
|
||||
*
|
||||
* @param inputStreamReader reader that points to the target test groups config
|
||||
* @return newly created {@link TestClassesFilter} object with the data contained at the given reader
|
||||
* @see #matches(String, String)
|
||||
*/
|
||||
@SuppressWarnings({"IOResourceOpenedButNotSafelyClosed"})
|
||||
public static TestClassesFilter createOn(InputStreamReader inputStreamReader) {
|
||||
try {
|
||||
Map<String, List<String>> groupNameToPatternsMap = new HashMap<String, List<String>>();
|
||||
String currentGroupName = "";
|
||||
LineNumberReader lineNumberReader = new LineNumberReader(inputStreamReader);
|
||||
String line;
|
||||
while ((line = lineNumberReader.readLine()) != null) {
|
||||
if (line.startsWith("#")) continue;
|
||||
if (line.startsWith("[") && line.endsWith("]")) {
|
||||
currentGroupName = line.substring(1, line.length() - 1);
|
||||
}
|
||||
else {
|
||||
if (!groupNameToPatternsMap.containsKey(currentGroupName)) {
|
||||
groupNameToPatternsMap.put(currentGroupName, new ArrayList<String>());
|
||||
}
|
||||
groupNameToPatternsMap.get(currentGroupName).add(line);
|
||||
}
|
||||
}
|
||||
|
||||
return new TestClassesFilter(groupNameToPatternsMap);
|
||||
}
|
||||
catch (IOException e) {
|
||||
return EMPTY_CLASSES_FILTER;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean matches(Collection<Pattern> patterns, String className) {
|
||||
protected static boolean matchesAnyPattern(Collection<Pattern> patterns, String className) {
|
||||
for (Pattern pattern : patterns) {
|
||||
if (pattern.matcher(className).matches()) {
|
||||
return true;
|
||||
@@ -162,48 +53,4 @@ public class TestClassesFilter {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to check if given class name belongs to the test group with the given name based on filtering rules encapsulated
|
||||
* at the current {@link TestClassesFilter} object. I.e. this method returns <code>true</code> if given test class name
|
||||
* is matched with any test class name filter configured for the test group with the given name.
|
||||
* <p/>
|
||||
* <b>Note:</b> there is a special case processing when given group name is {@link #ALL_EXCLUDE_DEFINED}. This method
|
||||
* returns <code>true</code> only if all registered patterns (for all test groups) don't match given test class name.
|
||||
*
|
||||
* @param className target test class name to check
|
||||
* @param groupName target test group name to check
|
||||
* @return <code>true</code> if given test group name is defined (not <code>null</code>) and test class with given
|
||||
* name belongs to the test group with given name;
|
||||
* <code>true</code> if given group if undefined or equal to {@link #ALL_EXCLUDE_DEFINED} and given test
|
||||
* class name is not matched by all registered patterns;
|
||||
* <code>false</code> otherwise
|
||||
*/
|
||||
public boolean matches(String className, String groupName) {
|
||||
List<Pattern> patterns = collectPatternsFor(groupName);
|
||||
boolean result = matches(patterns, className);
|
||||
//null group means all patterns from each defined group should be excluded
|
||||
if (isAllExcludeDefinedGroup(groupName)) {
|
||||
return !result;
|
||||
}
|
||||
else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isAllExcludeDefinedGroup(String groupName) {
|
||||
return StringUtil.isEmpty(groupName) || ALL_EXCLUDE_DEFINED.equalsIgnoreCase(groupName.trim());
|
||||
}
|
||||
|
||||
private List<Pattern> collectPatternsFor(String groupName) {
|
||||
if (isAllExcludeDefinedGroup(groupName)){
|
||||
return myAllPatterns;
|
||||
} else {
|
||||
if (!myPatterns.containsKey(groupName)){
|
||||
return EMPTY_LIST;
|
||||
} else {
|
||||
return myPatterns.get(groupName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user