-
Notifications
You must be signed in to change notification settings - Fork 376
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added matchers to check the visibility (public/private) of various re…
…flective elements. This is helpful, for example, when enforcing the scope of a public-facing API with a test, and provides stronger documentation for the future than mere comments.
- Loading branch information
jbrown
committed
Apr 12, 2020
1 parent
5dd6a62
commit ce29997
Showing
11 changed files
with
801 additions
and
0 deletions.
There are no files selected for viewing
50 changes: 50 additions & 0 deletions
50
hamcrest/src/main/java/org/hamcrest/visibility/AbstractVisibilityMatcher.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package org.hamcrest.visibility; | ||
|
||
import org.hamcrest.BaseMatcher; | ||
import org.hamcrest.Description; | ||
|
||
import java.lang.reflect.Member; | ||
|
||
abstract class AbstractVisibilityMatcher<T> extends BaseMatcher<T> | ||
{ | ||
/** | ||
* Should only ever be one of the values returned from | ||
* {@link VisibilityUtils#describeVisibility(Member)} and {@link VisibilityUtils#describeVisibility(Class)} | ||
**/ | ||
private final String expectedVisibility; | ||
|
||
AbstractVisibilityMatcher(String expectedVisibility) | ||
{ | ||
this.expectedVisibility = expectedVisibility; | ||
} | ||
|
||
@Override public void describeTo(Description description) | ||
{ | ||
description.appendText("is ").appendText(expectedVisibility); | ||
} | ||
|
||
@Override public void describeMismatch(Object item, Description description) | ||
{ | ||
if (item == null) | ||
{ | ||
description.appendText("was null"); | ||
} | ||
else if (item instanceof Class) | ||
{ | ||
description.appendText("was a ") | ||
.appendText(VisibilityUtils.describeVisibility((Class<?>) item)) | ||
.appendText(" class"); | ||
} | ||
else if (item instanceof Member) | ||
{ | ||
description.appendText("was a ") | ||
.appendText(VisibilityUtils.describeVisibility((Member) item)) | ||
.appendText(" ") | ||
.appendText(item.getClass().getName()); | ||
} | ||
else | ||
{ | ||
description.appendText("was "+item.getClass().getName()+" instead of a reflective element like a Class<T>, Constructor<T>, or Method"); | ||
} | ||
} | ||
} |
36 changes: 36 additions & 0 deletions
36
hamcrest/src/main/java/org/hamcrest/visibility/IsPackageProtected.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package org.hamcrest.visibility; | ||
|
||
import org.hamcrest.Matcher; | ||
|
||
import java.lang.reflect.Member; | ||
|
||
public class IsPackageProtected<T> extends AbstractVisibilityMatcher<T> | ||
{ | ||
public IsPackageProtected() | ||
{ | ||
super(VisibilityUtils.PACKAGE_PROTECTED_DESCRIPTION); | ||
} | ||
|
||
@Override | ||
public boolean matches(Object actual) | ||
{ | ||
if (actual == null) | ||
{ | ||
return false; | ||
} | ||
if (actual instanceof Class) | ||
{ | ||
return VisibilityUtils.isPackageProtected((Class<?>) actual); | ||
} | ||
if (actual instanceof Member) | ||
{ | ||
return VisibilityUtils.isPackageProtected((Member) actual); | ||
} | ||
return false; | ||
} | ||
|
||
public static <T> Matcher<T> isPackageProtected() | ||
{ | ||
return new IsPackageProtected<>(); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
hamcrest/src/main/java/org/hamcrest/visibility/IsPrivate.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package org.hamcrest.visibility; | ||
|
||
import org.hamcrest.Matcher; | ||
|
||
import java.lang.reflect.Member; | ||
|
||
public class IsPrivate<T> extends AbstractVisibilityMatcher<T> | ||
{ | ||
public IsPrivate(){ | ||
super(VisibilityUtils.PRIVATE_DESCRIPTION); | ||
} | ||
|
||
@Override | ||
public boolean matches(Object actual) | ||
{ | ||
if (actual == null) | ||
{ | ||
return false; | ||
} | ||
if (actual instanceof Class) | ||
{ | ||
return VisibilityUtils.isPrivate((Class<?>) actual); | ||
} | ||
if (actual instanceof Member) | ||
{ | ||
return VisibilityUtils.isPrivate((Member) actual); | ||
} | ||
return false; | ||
} | ||
|
||
public static <T> Matcher<T> isPrivate() | ||
{ | ||
return new IsPrivate<>(); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
hamcrest/src/main/java/org/hamcrest/visibility/IsProtected.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package org.hamcrest.visibility; | ||
|
||
import org.hamcrest.Matcher; | ||
|
||
import java.lang.reflect.Member; | ||
|
||
public class IsProtected<T> extends AbstractVisibilityMatcher<T> | ||
{ | ||
public IsProtected(){ | ||
super(VisibilityUtils.PROTECTED_DESCRIPTION); | ||
} | ||
|
||
@Override | ||
public boolean matches(Object actual) | ||
{ | ||
if (actual == null) | ||
{ | ||
return false; | ||
} | ||
if (actual instanceof Class) | ||
{ | ||
return VisibilityUtils.isProtected((Class<?>) actual); | ||
} | ||
if (actual instanceof Member) | ||
{ | ||
return VisibilityUtils.isProtected((Member) actual); | ||
} | ||
return false; | ||
} | ||
|
||
public static <T> Matcher<T> isProtected() | ||
{ | ||
return new IsProtected<>(); | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
hamcrest/src/main/java/org/hamcrest/visibility/IsPublic.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package org.hamcrest.visibility; | ||
|
||
import org.hamcrest.Matcher; | ||
|
||
import java.lang.reflect.Member; | ||
|
||
public class IsPublic<T> extends AbstractVisibilityMatcher<T> | ||
{ | ||
public IsPublic(){ | ||
super(VisibilityUtils.PUBLIC_DESCRIPTION); | ||
} | ||
|
||
@Override | ||
public boolean matches(Object actual) | ||
{ | ||
if (actual == null) | ||
{ | ||
return false; | ||
} | ||
if (actual instanceof Class) | ||
{ | ||
return VisibilityUtils.isPublic((Class<?>) actual); | ||
} | ||
if (actual instanceof Member) | ||
{ | ||
return VisibilityUtils.isPublic((Member) actual); | ||
} | ||
return false; | ||
} | ||
|
||
public static <T> Matcher<T> isPublic() | ||
{ | ||
return new IsPublic<>(); | ||
} | ||
} |
97 changes: 97 additions & 0 deletions
97
hamcrest/src/main/java/org/hamcrest/visibility/VisibilityUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package org.hamcrest.visibility; | ||
|
||
import java.lang.reflect.Member; | ||
import java.lang.reflect.Modifier; | ||
|
||
class VisibilityUtils | ||
{ | ||
|
||
static final String PUBLIC_DESCRIPTION = "public"; | ||
static final String PROTECTED_DESCRIPTION = "protected"; | ||
static final String PACKAGE_PROTECTED_DESCRIPTION = "package-protected (no modifiers)"; | ||
static final String PRIVATE_DESCRIPTION = "private"; | ||
|
||
static boolean isPublic(Class<?> clazz) | ||
{ | ||
return clazz != null && Modifier.isPublic(clazz.getModifiers()); | ||
} | ||
|
||
static boolean isProtected(Class<?> clazz) | ||
{ | ||
return clazz != null && Modifier.isProtected(clazz.getModifiers()); | ||
} | ||
|
||
static boolean isPackageProtected(Class<?> clazz) | ||
{ | ||
return clazz != null && !isPublic(clazz) && !isProtected(clazz) && !isPrivate(clazz); | ||
} | ||
|
||
static boolean isPrivate(Class<?> clazz) | ||
{ | ||
return clazz != null && Modifier.isPrivate(clazz.getModifiers()); | ||
} | ||
|
||
|
||
static boolean isPublic(Member member) | ||
{ | ||
return member != null && Modifier.isPublic(member.getModifiers()); | ||
} | ||
|
||
static boolean isProtected(Member member) | ||
{ | ||
return member != null && Modifier.isProtected(member.getModifiers()); | ||
} | ||
|
||
static boolean isPackageProtected(Member member) | ||
{ | ||
return member != null && !isPublic(member) && !isProtected(member) && !isPrivate(member); | ||
} | ||
|
||
static boolean isPrivate(Member member) | ||
{ | ||
return member != null && Modifier.isPrivate(member.getModifiers()); | ||
} | ||
|
||
|
||
static String describeVisibility(Class<?> clazz) | ||
{ | ||
if (isPublic(clazz)) | ||
{ | ||
return PUBLIC_DESCRIPTION; | ||
} | ||
if (isProtected(clazz)) | ||
{ | ||
return PROTECTED_DESCRIPTION; | ||
} | ||
if (isPackageProtected(clazz)) | ||
{ | ||
return PACKAGE_PROTECTED_DESCRIPTION; | ||
} | ||
if (isPrivate(clazz)) | ||
{ | ||
return PRIVATE_DESCRIPTION; | ||
} | ||
throw new IllegalArgumentException("Encountered unexpected visibility! This should NEVER happen."); | ||
} | ||
|
||
static String describeVisibility(Member member) | ||
{ | ||
if (isPublic(member)) | ||
{ | ||
return PUBLIC_DESCRIPTION; | ||
} | ||
if (isProtected(member)) | ||
{ | ||
return PROTECTED_DESCRIPTION; | ||
} | ||
if (isPackageProtected(member)) | ||
{ | ||
return PACKAGE_PROTECTED_DESCRIPTION; | ||
} | ||
if (isPrivate(member)) | ||
{ | ||
return PRIVATE_DESCRIPTION; | ||
} | ||
throw new IllegalArgumentException("Encountered unexpected visibility! This should NEVER happen."); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
</head> | ||
<body> | ||
<p>Matchers that perform checks on the visibility of reflective elements, such as Class<?> objects</p> | ||
</body> | ||
</html> |
Oops, something went wrong.