aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/junit/experimental/categories/Categories.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/junit/experimental/categories/Categories.java')
-rw-r--r--src/main/java/org/junit/experimental/categories/Categories.java108
1 files changed, 59 insertions, 49 deletions
diff --git a/src/main/java/org/junit/experimental/categories/Categories.java b/src/main/java/org/junit/experimental/categories/Categories.java
index 0c73ed8..290c180 100644
--- a/src/main/java/org/junit/experimental/categories/Categories.java
+++ b/src/main/java/org/junit/experimental/categories/Categories.java
@@ -2,10 +2,8 @@ package org.junit.experimental.categories;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
-import java.util.LinkedHashSet;
import java.util.Set;
import org.junit.runner.Description;
@@ -78,7 +76,7 @@ import org.junit.runners.model.RunnerBuilder;
* </pre>
*
* @version 4.12
- * @see <a href="https://github.com/junit-team/junit4/wiki/Categories">Categories at JUnit wiki</a>
+ * @see <a href="https://github.com/junit-team/junit/wiki/Categories">Categories at JUnit wiki</a>
*/
public class Categories extends Suite {
@@ -88,13 +86,13 @@ public class Categories extends Suite {
* Determines the tests to run that are annotated with categories specified in
* the value of this annotation or their subtypes unless excluded with {@link ExcludeCategory}.
*/
- Class<?>[] value() default {};
+ public Class<?>[] value() default {};
/**
* If <tt>true</tt>, runs tests annotated with <em>any</em> of the categories in
* {@link IncludeCategory#value()}. Otherwise, runs tests only if annotated with <em>all</em> of the categories.
*/
- boolean matchAny() default true;
+ public boolean matchAny() default true;
}
@Retention(RetentionPolicy.RUNTIME)
@@ -103,13 +101,13 @@ public class Categories extends Suite {
* Determines the tests which do not run if they are annotated with categories specified in the
* value of this annotation or their subtypes regardless of being included in {@link IncludeCategory#value()}.
*/
- Class<?>[] value() default {};
+ public Class<?>[] value() default {};
/**
* If <tt>true</tt>, the tests annotated with <em>any</em> of the categories in {@link ExcludeCategory#value()}
* do not run. Otherwise, the tests do not run if and only if annotated with <em>all</em> categories.
*/
- boolean matchAny() default true;
+ public boolean matchAny() default true;
}
public static class CategoryFilter extends Filter {
@@ -119,7 +117,10 @@ public class Categories extends Suite {
private final boolean excludedAny;
public static CategoryFilter include(boolean matchAny, Class<?>... categories) {
- return new CategoryFilter(matchAny, categories, true, null);
+ if (hasNull(categories)) {
+ throw new NullPointerException("has null category");
+ }
+ return categoryFilter(matchAny, createSet(categories), true, null);
}
public static CategoryFilter include(Class<?> category) {
@@ -131,7 +132,10 @@ public class Categories extends Suite {
}
public static CategoryFilter exclude(boolean matchAny, Class<?>... categories) {
- return new CategoryFilter(true, null, matchAny, categories);
+ if (hasNull(categories)) {
+ throw new NullPointerException("has null category");
+ }
+ return categoryFilter(true, null, matchAny, createSet(categories));
}
public static CategoryFilter exclude(Class<?> category) {
@@ -147,30 +151,14 @@ public class Categories extends Suite {
return new CategoryFilter(matchAnyInclusions, inclusions, matchAnyExclusions, exclusions);
}
- @Deprecated
- public CategoryFilter(Class<?> includedCategory, Class<?> excludedCategory) {
- includedAny = true;
- excludedAny = true;
- included = nullableClassToSet(includedCategory);
- excluded = nullableClassToSet(excludedCategory);
- }
-
protected CategoryFilter(boolean matchAnyIncludes, Set<Class<?>> includes,
- boolean matchAnyExcludes, Set<Class<?>> excludes) {
+ boolean matchAnyExcludes, Set<Class<?>> excludes) {
includedAny = matchAnyIncludes;
excludedAny = matchAnyExcludes;
included = copyAndRefine(includes);
excluded = copyAndRefine(excludes);
}
- private CategoryFilter(boolean matchAnyIncludes, Class<?>[] inclusions,
- boolean matchAnyExcludes, Class<?>[] exclusions) {
- includedAny = matchAnyIncludes;
- excludedAny = matchAnyExcludes;
- included = createSet(inclusions);
- excluded = createSet(exclusions);
- }
-
/**
* @see #toString()
*/
@@ -296,13 +284,23 @@ public class Categories extends Suite {
}
private static Set<Class<?>> copyAndRefine(Set<Class<?>> classes) {
- Set<Class<?>> c= new LinkedHashSet<Class<?>>();
+ HashSet<Class<?>> c= new HashSet<Class<?>>();
if (classes != null) {
c.addAll(classes);
}
c.remove(null);
return c;
}
+
+ private static boolean hasNull(Class<?>... classes) {
+ if (classes == null) return false;
+ for (Class<?> clazz : classes) {
+ if (clazz == null) {
+ return true;
+ }
+ }
+ return false;
+ }
}
public Categories(Class<?> klass, RunnerBuilder builder) throws InitializationError {
@@ -317,6 +315,7 @@ public class Categories extends Suite {
} catch (NoTestsRemainException e) {
throw new InitializationError(e);
}
+ assertNoCategorizedDescendentsOfUncategorizeableParents(getDescription());
}
private static Set<Class<?>> getIncludedCategory(Class<?> klass) {
@@ -339,6 +338,34 @@ public class Categories extends Suite {
return annotation == null || annotation.matchAny();
}
+ private static void assertNoCategorizedDescendentsOfUncategorizeableParents(Description description) throws InitializationError {
+ if (!canHaveCategorizedChildren(description)) {
+ assertNoDescendantsHaveCategoryAnnotations(description);
+ }
+ for (Description each : description.getChildren()) {
+ assertNoCategorizedDescendentsOfUncategorizeableParents(each);
+ }
+ }
+
+ private static void assertNoDescendantsHaveCategoryAnnotations(Description description) throws InitializationError {
+ for (Description each : description.getChildren()) {
+ if (each.getAnnotation(Category.class) != null) {
+ throw new InitializationError("Category annotations on Parameterized classes are not supported on individual methods.");
+ }
+ assertNoDescendantsHaveCategoryAnnotations(each);
+ }
+ }
+
+ // If children have names like [0], our current magical category code can't determine their parentage.
+ private static boolean canHaveCategorizedChildren(Description description) {
+ for (Description each : description.getChildren()) {
+ if (each.getTestClass() == null) {
+ return false;
+ }
+ }
+ return true;
+ }
+
private static boolean hasAssignableTo(Set<Class<?>> assigns, Class<?> to) {
for (final Class<?> from : assigns) {
if (to.isAssignableFrom(from)) {
@@ -348,28 +375,11 @@ public class Categories extends Suite {
return false;
}
- private static Set<Class<?>> createSet(Class<?>[] classes) {
- // Not throwing a NPE if t is null is a bad idea, but it's the behavior from JUnit 4.12
- // for include(boolean, Class<?>...) and exclude(boolean, Class<?>...)
- if (classes == null || classes.length == 0) {
- return Collections.emptySet();
- }
- for (Class<?> category : classes) {
- if (category == null) {
- throw new NullPointerException("has null category");
- }
+ private static Set<Class<?>> createSet(Class<?>... t) {
+ final Set<Class<?>> set= new HashSet<Class<?>>();
+ if (t != null) {
+ Collections.addAll(set, t);
}
-
- return classes.length == 1
- ? Collections.<Class<?>>singleton(classes[0])
- : new LinkedHashSet<Class<?>>(Arrays.asList(classes));
- }
-
- private static Set<Class<?>> nullableClassToSet(Class<?> nullableClass) {
- // Not throwing a NPE if t is null is a bad idea, but it's the behavior from JUnit 4.11
- // for CategoryFilter(Class<?> includedCategory, Class<?> excludedCategory)
- return nullableClass == null
- ? Collections.<Class<?>>emptySet()
- : Collections.<Class<?>>singleton(nullableClass);
+ return set;
}
}