Skip to content

Commit d112596

Browse files
authored
Add public CategoryFilter constructor that was removed in JUnit 4.12 (#1403)
* Add back public CategoryFilter constructor that was removed in JUnit 4.12. * Remove duplicated code that handles null categories. * Change CategoryFilter to use LinkedHashSet(). This makes describe() and toString() print the categories in the same order that they were provided to the user.
1 parent ae28d97 commit d112596

File tree

2 files changed

+72
-26
lines changed

2 files changed

+72
-26
lines changed

Diff for: src/main/java/org/junit/experimental/categories/Categories.java

+44-25
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import java.lang.annotation.Retention;
44
import java.lang.annotation.RetentionPolicy;
5+
import java.util.Arrays;
56
import java.util.Collections;
67
import java.util.HashSet;
8+
import java.util.LinkedHashSet;
79
import java.util.Set;
810

911
import org.junit.runner.Description;
@@ -117,10 +119,7 @@ public static class CategoryFilter extends Filter {
117119
private final boolean excludedAny;
118120

119121
public static CategoryFilter include(boolean matchAny, Class<?>... categories) {
120-
if (hasNull(categories)) {
121-
throw new NullPointerException("has null category");
122-
}
123-
return categoryFilter(matchAny, createSet(categories), true, null);
122+
return new CategoryFilter(matchAny, categories, true, null);
124123
}
125124

126125
public static CategoryFilter include(Class<?> category) {
@@ -132,10 +131,7 @@ public static CategoryFilter include(Class<?>... categories) {
132131
}
133132

134133
public static CategoryFilter exclude(boolean matchAny, Class<?>... categories) {
135-
if (hasNull(categories)) {
136-
throw new NullPointerException("has null category");
137-
}
138-
return categoryFilter(true, null, matchAny, createSet(categories));
134+
return new CategoryFilter(true, null, matchAny, categories);
139135
}
140136

141137
public static CategoryFilter exclude(Class<?> category) {
@@ -151,14 +147,30 @@ public static CategoryFilter categoryFilter(boolean matchAnyInclusions, Set<Clas
151147
return new CategoryFilter(matchAnyInclusions, inclusions, matchAnyExclusions, exclusions);
152148
}
153149

150+
@Deprecated
151+
public CategoryFilter(Class<?> includedCategory, Class<?> excludedCategory) {
152+
includedAny = true;
153+
excludedAny = true;
154+
included = nullableClassToSet(includedCategory);
155+
excluded = nullableClassToSet(excludedCategory);
156+
}
157+
154158
protected CategoryFilter(boolean matchAnyIncludes, Set<Class<?>> includes,
155-
boolean matchAnyExcludes, Set<Class<?>> excludes) {
159+
boolean matchAnyExcludes, Set<Class<?>> excludes) {
156160
includedAny = matchAnyIncludes;
157161
excludedAny = matchAnyExcludes;
158162
included = copyAndRefine(includes);
159163
excluded = copyAndRefine(excludes);
160164
}
161165

166+
private CategoryFilter(boolean matchAnyIncludes, Class<?>[] inclusions,
167+
boolean matchAnyExcludes, Class<?>[] exclusions) {
168+
includedAny = matchAnyIncludes;
169+
excludedAny = matchAnyExcludes;
170+
included = createSet(inclusions);
171+
excluded = createSet(exclusions);
172+
}
173+
162174
/**
163175
* @see #toString()
164176
*/
@@ -284,23 +296,13 @@ private static Class<?>[] directCategories(Description description) {
284296
}
285297

286298
private static Set<Class<?>> copyAndRefine(Set<Class<?>> classes) {
287-
Set<Class<?>> c= new HashSet<Class<?>>();
299+
Set<Class<?>> c= new LinkedHashSet<Class<?>>();
288300
if (classes != null) {
289301
c.addAll(classes);
290302
}
291303
c.remove(null);
292304
return c;
293305
}
294-
295-
private static boolean hasNull(Class<?>... classes) {
296-
if (classes == null) return false;
297-
for (Class<?> clazz : classes) {
298-
if (clazz == null) {
299-
return true;
300-
}
301-
}
302-
return false;
303-
}
304306
}
305307

306308
public Categories(Class<?> klass, RunnerBuilder builder) throws InitializationError {
@@ -346,11 +348,28 @@ private static boolean hasAssignableTo(Set<Class<?>> assigns, Class<?> to) {
346348
return false;
347349
}
348350

349-
private static Set<Class<?>> createSet(Class<?>... t) {
350-
final Set<Class<?>> set= new HashSet<Class<?>>();
351-
if (t != null) {
352-
Collections.addAll(set, t);
351+
private static Set<Class<?>> createSet(Class<?>[] classes) {
352+
// Not throwing a NPE if t is null is a bad idea, but it's the behavior from JUnit 4.12
353+
// for include(boolean, Class<?>...) and exclude(boolean, Class<?>...)
354+
if (classes == null || classes.length == 0) {
355+
return Collections.emptySet();
356+
}
357+
for (Class<?> category : classes) {
358+
if (category == null) {
359+
throw new NullPointerException("has null category");
360+
}
353361
}
354-
return set;
362+
363+
return classes.length == 1
364+
? Collections.<Class<?>>singleton(classes[0])
365+
: new LinkedHashSet<Class<?>>(Arrays.asList(classes));
366+
}
367+
368+
private static Set<Class<?>> nullableClassToSet(Class<?> nullableClass) {
369+
// Not throwing a NPE if t is null is a bad idea, but it's the behavior from JUnit 4.11
370+
// for CategoryFilter(Class<?> includedCategory, Class<?> excludedCategory)
371+
return nullableClass == null
372+
? Collections.<Class<?>>emptySet()
373+
: Collections.<Class<?>>singleton(nullableClass);
355374
}
356375
}

Diff for: src/test/java/org/junit/experimental/categories/CategoryTest.java

+28-1
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,32 @@ public static class TestSuiteWithNoCategories {
179179
}
180180

181181
@Test
182-
public void testCountWithExplicitFilter() throws Throwable {
182+
public void testCountWithExplicitIncludeFilter() throws Throwable {
183183
CategoryFilter include = CategoryFilter.include(SlowTests.class);
184184
Request baseRequest = Request.aClass(TestSuiteWithNoCategories.class);
185185
Result result = new JUnitCore().run(baseRequest.filterWith(include));
186186
assertTrue(result.wasSuccessful());
187187
assertEquals(2, result.getRunCount());
188188
}
189189

190+
@Test
191+
public void testCountWithExplicitExcludeFilter() throws Throwable {
192+
CategoryFilter include = CategoryFilter.exclude(SlowTests.class);
193+
Request baseRequest = Request.aClass(TestSuiteWithNoCategories.class);
194+
Result result = new JUnitCore().run(baseRequest.filterWith(include));
195+
assertEquals(2, result.getFailureCount());
196+
assertEquals(2, result.getRunCount());
197+
}
198+
199+
@Test
200+
public void testCountWithExplicitExcludeFilter_usingConstructor() throws Throwable {
201+
CategoryFilter include = new CategoryFilter(null, SlowTests.class);
202+
Request baseRequest = Request.aClass(TestSuiteWithNoCategories.class);
203+
Result result = new JUnitCore().run(baseRequest.filterWith(include));
204+
assertEquals(2, result.getFailureCount());
205+
assertEquals(2, result.getRunCount());
206+
}
207+
190208
@Test
191209
public void categoryFilterLeavesOnlyMatchingMethods()
192210
throws InitializationError, NoTestsRemainException {
@@ -196,6 +214,15 @@ public void categoryFilterLeavesOnlyMatchingMethods()
196214
assertEquals(1, runner.testCount());
197215
}
198216

217+
@Test
218+
public void categoryFilterLeavesOnlyMatchingMethods_usingConstructor()
219+
throws InitializationError, NoTestsRemainException {
220+
CategoryFilter filter = new CategoryFilter(SlowTests.class, null);
221+
BlockJUnit4ClassRunner runner = new BlockJUnit4ClassRunner(A.class);
222+
filter.apply(runner);
223+
assertEquals(1, runner.testCount());
224+
}
225+
199226
public static class OneFastOneSlow {
200227
@Category(FastTests.class)
201228
@Test

0 commit comments

Comments
 (0)