Skip to content

Commit

Permalink
Merge pull request #236 from lutovich/issue109-tests-junit-commons
Browse files Browse the repository at this point in the history
* issue109-tests-junit-commons:
  Polishing
  Fix fragile test
  Improved test coverage for ToStringBuilder
  Removed StringUtils#join()
  Improved test coverage for ReflectionUtils
  Improved test coverage for Preconditions
  Improved test coverage for ExceptionUtils
  Improved test coverage for ClasspathScanner
  Improved test coverage for AnnotationUtils
  • Loading branch information
sbrannen committed May 6, 2016
2 parents 7626b32 + 1cdc6e6 commit 2dfd654
Show file tree
Hide file tree
Showing 14 changed files with 1,241 additions and 146 deletions.
Expand Up @@ -71,7 +71,7 @@ public static boolean isAnnotated(AnnotatedElement element, Class<? extends Anno
* the supplied {@code element}.
*/
public static <A extends Annotation> Optional<A> findAnnotation(AnnotatedElement element, Class<A> annotationType) {
return findAnnotation(element, annotationType, new HashSet<Annotation>());
return findAnnotation(element, annotationType, new HashSet<>());
}

@SuppressWarnings("unchecked")
Expand Down Expand Up @@ -99,15 +99,10 @@ private static <A extends Annotation> Optional<A> findAnnotation(AnnotatedElemen
}

// Meta-present on directly present annotations?
for (Annotation candidateAnnotation : element.getDeclaredAnnotations()) {
if (!isInJavaLangAnnotationPackage(candidateAnnotation) && visited.add(candidateAnnotation)) {
Optional<A> metaAnnotation = findAnnotation(candidateAnnotation.annotationType(), annotationType,
visited);
if (metaAnnotation.isPresent()) {
annotationCache.put(key, metaAnnotation.get());
return metaAnnotation;
}
}
Optional<A> directMetaAnnotation = findMetaAnnotation(annotationType, element.getDeclaredAnnotations(), key,
visited);
if (directMetaAnnotation.isPresent()) {
return directMetaAnnotation;
}

// Indirectly present?
Expand All @@ -118,7 +113,18 @@ private static <A extends Annotation> Optional<A> findAnnotation(AnnotatedElemen
}

// Meta-present on indirectly present annotations?
for (Annotation candidateAnnotation : element.getAnnotations()) {
Optional<A> indirectMetaAnnotation = findMetaAnnotation(annotationType, element.getAnnotations(), key, visited);
if (indirectMetaAnnotation.isPresent()) {
return indirectMetaAnnotation;
}

return Optional.empty();
}

private static <A extends Annotation> Optional<A> findMetaAnnotation(Class<A> annotationType,
Annotation[] candidates, AnnotationCacheKey key, Set<Annotation> visited) {

for (Annotation candidateAnnotation : candidates) {
if (!isInJavaLangAnnotationPackage(candidateAnnotation) && visited.add(candidateAnnotation)) {
Optional<A> metaAnnotation = findAnnotation(candidateAnnotation.annotationType(), annotationType,
visited);
Expand All @@ -128,7 +134,6 @@ private static <A extends Annotation> Optional<A> findAnnotation(AnnotatedElemen
}
}
}

return Optional.empty();
}

Expand Down
Expand Up @@ -51,6 +51,8 @@ class ClasspathScanner {
}

boolean isPackage(String packageName) {
Preconditions.notBlank(packageName, "package name must not be null or empty");

String path = packagePath(packageName);
try {
Enumeration<URL> resource = classLoaderSupplier.get().getResources(path);
Expand Down Expand Up @@ -109,6 +111,8 @@ private String packagePath(String basePackageName) {

private List<Class<?>> findClassesInSourceDirRecursively(File sourceDir, String packageName,
Predicate<Class<?>> classFilter) {
Preconditions.notNull(classFilter, "classFilter must not be null");

List<Class<?>> classesCollector = new ArrayList<>();
collectClassesRecursively(sourceDir, packageName, classesCollector, classFilter);
return classesCollector;
Expand All @@ -123,7 +127,7 @@ private void collectClassesRecursively(File sourceDir, String packageName, List<
for (File file : files) {
if (isClassFile(file)) {
Optional<Class<?>> classForClassFile = loadClassForClassFile(file, packageName);
classForClassFile.filter(classFilter).ifPresent(clazz -> classesCollector.add(clazz));
classForClassFile.filter(classFilter).ifPresent(classesCollector::add);
}
else if (file.isDirectory()) {
collectClassesRecursively(file, appendPackageName(packageName, file.getName()), classesCollector,
Expand Down
Expand Up @@ -247,7 +247,7 @@ public static Optional<Method> loadMethod(String fullyQualifiedMethodName) {
return testMethodOptional;
}

public static Optional<Object> getOuterInstance(Object inner) {
private static Optional<Object> getOuterInstance(Object inner) {
// This is risky since it depends on the name of the field which is nowhere guaranteed
// but has been stable so far in all JDKs

Expand All @@ -263,6 +263,9 @@ public static Optional<Object> getOuterInstance(Object inner) {
}

public static Optional<Object> getOuterInstance(Object inner, Class<?> targetType) {
Preconditions.notNull(inner, "inner object must not be null");
Preconditions.notNull(targetType, "targetType must not be null");

if (targetType.isInstance(inner))
return Optional.of(inner);
Optional<Object> candidate = getOuterInstance(inner);
Expand All @@ -280,9 +283,8 @@ public static boolean isPackage(String packageName) {
public static Set<File> getAllClasspathRootDirectories() {
// TODO This is quite a hack, since sometimes the classpath is quite different
String fullClassPath = System.getProperty("java.class.path");
final String separator = System.getProperty("path.separator");
// @formatter:off
return Arrays.stream(fullClassPath.split(separator))
return Arrays.stream(fullClassPath.split(File.pathSeparator))
.filter(part -> !part.endsWith(".jar"))
.map(File::new)
.filter(File::isDirectory)
Expand Down Expand Up @@ -346,11 +348,10 @@ public static List<Method> findMethods(Class<?> clazz, Predicate<Method> predica
/**
* Return all methods in superclass hierarchy except from Object.
*/
public static List<Method> findAllMethodsInHierarchy(Class<?> clazz, MethodSortOrder sortOrder) {
private static List<Method> findAllMethodsInHierarchy(Class<?> clazz, MethodSortOrder sortOrder) {
Preconditions.notNull(clazz, "Class must not be null");
Preconditions.notNull(sortOrder, "MethodSortOrder must not be null");

// TODO Support interface default methods.
// TODO Determine if we need to support bridged methods.

List<Method> localMethods = Arrays.asList(clazz.getDeclaredMethods());
Expand Down Expand Up @@ -446,16 +447,9 @@ private static boolean isMethodShadowedBy(Method upper, Method lower) {
if (!lower.getName().equals(upper.getName())) {
return false;
}
Class<?>[] lowerParameterTypes = lower.getParameterTypes();
Class<?>[] upperParameterTypes = upper.getParameterTypes();
if (lowerParameterTypes.length != upperParameterTypes.length) {
if (!Arrays.equals(lower.getParameterTypes(), upper.getParameterTypes())) {
return false;
}
for (int i = 0; i < lowerParameterTypes.length; i++) {
if (!lowerParameterTypes[i].equals(upperParameterTypes[i])) {
return false;
}
}
return true;
}

Expand Down Expand Up @@ -491,6 +485,8 @@ private static Throwable getUnderlyingCause(Throwable t) {
* @see Class#isAssignableFrom
*/
public static Set<Class<?>> getAllAssignmentCompatibleClasses(Class<?> clazz) {
Preconditions.notNull(clazz, "class must not be null");

Set<Class<?>> result = new LinkedHashSet<>();
getAllAssignmentCompatibleClasses(clazz, result);
return result;
Expand Down
Expand Up @@ -14,8 +14,6 @@
import static java.util.stream.Collectors.joining;
import static org.junit.gen5.commons.meta.API.Usage.Internal;

import java.util.stream.Stream;

import org.junit.gen5.commons.meta.API;

/**
Expand Down Expand Up @@ -74,18 +72,7 @@ public static String nullSafeToString(Class<?>... classes) {
if (classes == null || classes.length == 0) {
return "";
}
return join(stream(classes).map(Class::getName), ", ");
}

/**
* Join a stream of {@link String}s together.
*
* @param stringStream the stream of Stings
* @param delimiter the delimiter between elements
* @return the joined string
*/
public static String join(Stream<String> stringStream, String delimiter) {
return stringStream.collect(joining(delimiter));
return stream(classes).map(Class::getName).collect(joining(", "));
}

}
Expand Up @@ -10,23 +10,26 @@

package org.junit.gen5.engine;

import static java.util.stream.Collectors.joining;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.junit.gen5.commons.JUnitException;
import org.junit.gen5.commons.util.Preconditions;
import org.junit.gen5.commons.util.StringUtils;
import org.junit.gen5.engine.UniqueId.Segment;

/**
* Used to parse a unique ID string representation into a {@link UniqueId}
* or to format a {@link UniqueId uniqueId} into a string representation.
* or to format a {@link UniqueId} into a string representation.
*
* @since 5.0
*/
public class UniqueIdFormat {

private final char openSegment;
private final char closeSegment;
private final char segmentDelimiter;
Expand All @@ -47,43 +50,47 @@ public UniqueIdFormat(char openSegment, char typeValueSeparator, char closeSegme
}

public UniqueId parse(String source) {
String[] parts = source.split(Character.toString(segmentDelimiter));
String[] parts = source.split(Character.toString(this.segmentDelimiter));
List<Segment> segments = Arrays.stream(parts).map(this::createSegment).collect(Collectors.toList());
return new UniqueId(segments);
}

private Segment createSegment(String segmentString) {
Matcher segmentMatcher = segmentPattern.matcher(segmentString);
if (!segmentMatcher.matches())
Matcher segmentMatcher = this.segmentPattern.matcher(segmentString);
if (!segmentMatcher.matches()) {
throw new JUnitException(String.format("'%s' is not a well-formed UniqueId segment", segmentString));
}
String type = checkAllowed(segmentMatcher.group(1));
String value = checkAllowed(segmentMatcher.group(2));
return new Segment(type, value);
}

private String checkAllowed(String typeOrValue) {
checkDoesNotContain(typeOrValue, segmentDelimiter);
checkDoesNotContain(typeOrValue, typeValueSeparator);
checkDoesNotContain(typeOrValue, openSegment);
checkDoesNotContain(typeOrValue, closeSegment);
checkDoesNotContain(typeOrValue, this.segmentDelimiter);
checkDoesNotContain(typeOrValue, this.typeValueSeparator);
checkDoesNotContain(typeOrValue, this.openSegment);
checkDoesNotContain(typeOrValue, this.closeSegment);
return typeOrValue;
}

private void checkDoesNotContain(String typeOrValue, char forbiddenString) {
Preconditions.condition(typeOrValue.indexOf(forbiddenString) < 0,
String.format("type or value '%s' must not contain '%s'", typeOrValue, forbiddenString));
private void checkDoesNotContain(String typeOrValue, char forbiddenCharacter) {
Preconditions.condition(typeOrValue.indexOf(forbiddenCharacter) < 0,
() -> String.format("type or value '%s' must not contain '%s'", typeOrValue, forbiddenCharacter));
}

/**
* Create and deliver the string representation of the {@code UniqueId}
* Format and return the string representation of the supplied {@code UniqueId}.
*/
public String format(UniqueId uniqueId) {
Stream<String> segmentStream = uniqueId.getSegments().stream().map(this::describe);
return StringUtils.join(segmentStream, Character.toString(segmentDelimiter));
// @formatter:off
return uniqueId.getSegments().stream()
.map(this::describe)
.collect(joining(Character.toString(this.segmentDelimiter)));
// @formatter:on
}

private String describe(Segment segment) {
return String.format("[%s%s%s]", segment.getType(), typeValueSeparator, segment.getValue());
return String.format("[%s%s%s]", segment.getType(), this.typeValueSeparator, segment.getValue());
}

}

0 comments on commit 2dfd654

Please sign in to comment.