From 5d68c458a2201a3cfbcf4326a89abe0773d971cb Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Sun, 21 Feb 2021 15:27:40 +0100 Subject: [PATCH 1/2] make `metaAnnotated` predicates also match direct annotations So far the most common use case for checking rules for meta-annotations seems to be annotation composition, where users want to test that certain classes/members are either directly annotated with some annotation, or with some annotation that is meta-annotated with the respective annotation. Thus it makes sense to cover this use case directly with the `metaAnnotated(..)` syntax. For example ``` @interface A{} @A @interface B{} class Foo { @A Object directlyAnnotated; @B Object indirectlyAnnotated; } ``` Previously only `indirectlyAnnotated` would have counted as meta-annotated with `@A`. Now we count both those methods as meta-annotated with `@A`. The old behavior of really being annotated only through the hierarchy, but not directly can still be expressed as `metaAnnotatedWith(A.class).and(not(annotatedWith(A.class)))`, which seems to be good enough still to cover the old behavior. Besides that the only use case I could imagine is to enforce the use of a custom composite annotation, which could also be achieved by simply forbidding the original annotation altogether. Signed-off-by: Peter Gafert --- .../domain/properties/CanBeAnnotated.java | 6 +++- .../core/domain/AccessTargetTest.java | 10 ++++-- .../archunit/core/domain/JavaClassTest.java | 8 +++-- .../archunit/core/domain/JavaMemberTest.java | 24 +++++++++---- .../syntax/elements/GivenClassesThatTest.java | 12 +++---- ...GivenMembersDeclaredInClassesThatTest.java | 12 +++---- .../elements/ShouldClassesThatTest.java | 36 +++++++++---------- .../elements/ShouldOnlyByClassesThatTest.java | 33 ++++++++++------- 8 files changed, 87 insertions(+), 54 deletions(-) diff --git a/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/CanBeAnnotated.java b/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/CanBeAnnotated.java index 2c4eafa0f3..4132fb1a0f 100644 --- a/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/CanBeAnnotated.java +++ b/archunit/src/main/java/com/tngtech/archunit/core/domain/properties/CanBeAnnotated.java @@ -175,8 +175,12 @@ private static boolean isMetaAnnotatedWith( return false; } + if (predicate.apply(annotation)) { + return true; + } + for (JavaAnnotation metaAnnotation : annotation.getRawType().getAnnotations()) { - if (predicate.apply(metaAnnotation) || isMetaAnnotatedWith(metaAnnotation, predicate, visitedAnnotations)) { + if (isMetaAnnotatedWith(metaAnnotation, predicate, visitedAnnotations)) { return true; } } diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/AccessTargetTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/AccessTargetTest.java index 8a70dfbd7c..fecadb7ddc 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/AccessTargetTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/AccessTargetTest.java @@ -75,10 +75,13 @@ public void isMetaAnnotatedWith_type_on_resolved_target() { assertThat(call.getTarget().isMetaAnnotatedWith(QueriedAnnotation.class)) .as("target is meta-annotated with @" + QueriedAnnotation.class.getSimpleName()) - .isFalse(); + .isTrue(); assertThat(call.getTarget().isMetaAnnotatedWith(Retention.class)) .as("target is meta-annotated with @" + Retention.class.getSimpleName()) .isTrue(); + assertThat(call.getTarget().isMetaAnnotatedWith(Deprecated.class)) + .as("target is meta-annotated with @" + Deprecated.class.getSimpleName()) + .isFalse(); } @Test @@ -88,10 +91,13 @@ public void isMetaAnnotatedWith_typeName_on_resolved_target() { assertThat(call.getTarget().isMetaAnnotatedWith(QueriedAnnotation.class.getName())) .as("target is meta-annotated with @" + QueriedAnnotation.class.getSimpleName()) - .isFalse(); + .isTrue(); assertThat(call.getTarget().isMetaAnnotatedWith(Retention.class.getName())) .as("target is meta-annotated with @" + Retention.class.getSimpleName()) .isTrue(); + assertThat(call.getTarget().isMetaAnnotatedWith(Deprecated.class)) + .as("target is meta-annotated with @" + Deprecated.class.getSimpleName()) + .isFalse(); } @Test diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaClassTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaClassTest.java index b764a45f62..5b5eb8da41 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaClassTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaClassTest.java @@ -320,9 +320,11 @@ public void isMetaAnnotatedWith_type() { JavaClass clazz = importClassesWithContext(Parent.class, SomeAnnotation.class).get(Parent.class); assertThat(clazz.isMetaAnnotatedWith(SomeAnnotation.class)) - .as("Parent is meta-annotated with @" + SomeAnnotation.class.getSimpleName()).isFalse(); + .as("Parent is meta-annotated with @" + SomeAnnotation.class.getSimpleName()).isTrue(); assertThat(clazz.isMetaAnnotatedWith(Retention.class)) .as("Parent is meta-annotated with @" + Retention.class.getSimpleName()).isTrue(); + assertThat(clazz.isMetaAnnotatedWith(Deprecated.class)) + .as("Parent is meta-annotated with @" + Deprecated.class.getSimpleName()).isFalse(); } @Test @@ -330,9 +332,11 @@ public void isMetaAnnotatedWith_typeName() { JavaClass clazz = importClassesWithContext(Parent.class, SomeAnnotation.class).get(Parent.class); assertThat(clazz.isMetaAnnotatedWith(SomeAnnotation.class.getName())) - .as("Parent is meta-annotated with @" + SomeAnnotation.class.getSimpleName()).isFalse(); + .as("Parent is meta-annotated with @" + SomeAnnotation.class.getSimpleName()).isTrue(); assertThat(clazz.isMetaAnnotatedWith(Retention.class.getName())) .as("Parent is meta-annotated with @" + Retention.class.getSimpleName()).isTrue(); + assertThat(clazz.isMetaAnnotatedWith(Deprecated.class.getName())) + .as("Parent is meta-annotated with @" + Deprecated.class.getSimpleName()).isFalse(); } @Test diff --git a/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaMemberTest.java b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaMemberTest.java index f5c7954a2e..012a53325c 100644 --- a/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaMemberTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/core/domain/JavaMemberTest.java @@ -10,11 +10,12 @@ import static com.tngtech.archunit.core.domain.TestUtils.importClassWithContext; import static com.tngtech.archunit.core.domain.TestUtils.importClassesWithContext; import static com.tngtech.archunit.testutil.Assertions.assertThat; +import static java.lang.annotation.RetentionPolicy.RUNTIME; public class JavaMemberTest { @Test public void isAnnotatedWith_type() { - assertThat(importField(SomeClass.class, "someField").isAnnotatedWith(Deprecated.class)) + assertThat(importField(SomeClass.class, "someField").isAnnotatedWith(SomeAnnotation.class)) .as("field is annotated with @Deprecated").isTrue(); assertThat(importField(SomeClass.class, "someField").isAnnotatedWith(Retention.class)) .as("field is annotated with @Retention").isFalse(); @@ -22,7 +23,7 @@ public void isAnnotatedWith_type() { @Test public void isAnnotatedWith_typeName() { - assertThat(importField(SomeClass.class, "someField").isAnnotatedWith(Deprecated.class.getName())) + assertThat(importField(SomeClass.class, "someField").isAnnotatedWith(SomeAnnotation.class.getName())) .as("field is annotated with @Deprecated").isTrue(); assertThat(importField(SomeClass.class, "someField").isAnnotatedWith(Retention.class.getName())) .as("field is annotated with @Retention").isFalse(); @@ -42,20 +43,24 @@ public void isAnnotatedWith_predicate() { public void isMetaAnnotatedWith_type() { JavaClass clazz = importClassesWithContext(SomeClass.class, Deprecated.class).get(SomeClass.class); - assertThat(clazz.getField("someField").isMetaAnnotatedWith(Deprecated.class)) - .as("field is meta-annotated with @Deprecated").isFalse(); + assertThat(clazz.getField("someField").isMetaAnnotatedWith(SomeAnnotation.class)) + .as("field is meta-annotated with @SomeAnnotation").isTrue(); assertThat(clazz.getField("someField").isMetaAnnotatedWith(Retention.class)) .as("field is meta-annotated with @Retention").isTrue(); + assertThat(clazz.getField("someField").isMetaAnnotatedWith(Deprecated.class)) + .as("field is meta-annotated with @Deprecated").isFalse(); } @Test public void isMetaAnnotatedWith_typeName() { JavaClass clazz = importClassesWithContext(SomeClass.class, Deprecated.class).get(SomeClass.class); - assertThat(clazz.getField("someField").isMetaAnnotatedWith(Deprecated.class.getName())) - .as("field is meta-annotated with @Deprecated").isFalse(); + assertThat(clazz.getField("someField").isMetaAnnotatedWith(SomeAnnotation.class.getName())) + .as("field is meta-annotated with @SomeAnnotation").isTrue(); assertThat(clazz.getField("someField").isMetaAnnotatedWith(Retention.class.getName())) .as("field is meta-annotated with @Retention").isTrue(); + assertThat(clazz.getField("someField").isMetaAnnotatedWith(Deprecated.class.getName())) + .as("field is meta-annotated with @Deprecated").isFalse(); } @Test @@ -93,8 +98,13 @@ private static JavaField importField(Class owner, String name) { return importClassWithContext(owner).getField(name); } + @Retention(RUNTIME) + private @interface SomeAnnotation { + } + + @SuppressWarnings("unused") private static class SomeClass { - @Deprecated + @SomeAnnotation private String someField; } } diff --git a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenClassesThatTest.java b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenClassesThatTest.java index 2467638585..6557412cc0 100644 --- a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenClassesThatTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenClassesThatTest.java @@ -340,7 +340,7 @@ public void areMetaAnnotatedWith_type() { List classes = filterResultOf(classes().that().areMetaAnnotatedWith(SomeAnnotation.class)) .on(MetaAnnotatedClass.class, AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatType(getOnlyElement(classes)).matches(MetaAnnotatedClass.class); + assertThatTypes(classes).matchInAnyOrder(MetaAnnotatedClass.class, AnnotatedClass.class, MetaAnnotatedAnnotation.class); } @Test @@ -348,7 +348,7 @@ public void areNotMetaAnnotatedWith_type() { List classes = filterResultOf(classes().that().areNotMetaAnnotatedWith(SomeAnnotation.class)) .on(MetaAnnotatedClass.class, AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); + assertThatTypes(classes).matchInAnyOrder(SimpleClass.class); } @Test @@ -356,7 +356,7 @@ public void areMetaAnnotatedWith_typeName() { List classes = filterResultOf(classes().that().areMetaAnnotatedWith(SomeAnnotation.class.getName())) .on(MetaAnnotatedClass.class, AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatType(getOnlyElement(classes)).matches(MetaAnnotatedClass.class); + assertThatTypes(classes).matchInAnyOrder(MetaAnnotatedClass.class, AnnotatedClass.class, MetaAnnotatedAnnotation.class); } @Test @@ -364,7 +364,7 @@ public void areNotMetaAnnotatedWith_typeName() { List classes = filterResultOf(classes().that().areNotMetaAnnotatedWith(SomeAnnotation.class.getName())) .on(MetaAnnotatedClass.class, AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); + assertThatTypes(classes).matchInAnyOrder(SimpleClass.class); } @Test @@ -373,7 +373,7 @@ public void areMetaAnnotatedWith_predicate() { List classes = filterResultOf(classes().that().areMetaAnnotatedWith(hasNamePredicate)) .on(MetaAnnotatedClass.class, AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatType(getOnlyElement(classes)).matches(MetaAnnotatedClass.class); + assertThatTypes(classes).matchInAnyOrder(MetaAnnotatedClass.class, AnnotatedClass.class, MetaAnnotatedAnnotation.class); } @Test @@ -382,7 +382,7 @@ public void areNotMetaAnnotatedWith_predicate() { List classes = filterResultOf(classes().that().areNotMetaAnnotatedWith(hasNamePredicate)) .on(MetaAnnotatedClass.class, AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); + assertThatTypes(classes).matchInAnyOrder(SimpleClass.class); } @Test diff --git a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenMembersDeclaredInClassesThatTest.java b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenMembersDeclaredInClassesThatTest.java index f47a76f8bb..060ccd8e50 100644 --- a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenMembersDeclaredInClassesThatTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/GivenMembersDeclaredInClassesThatTest.java @@ -336,7 +336,7 @@ public void areMetaAnnotatedWith_type() { List members = filterResultOf(members().that().areDeclaredInClassesThat().areMetaAnnotatedWith(SomeAnnotation.class)) .on(MetaAnnotatedClass.class, AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatMembers(members).matchInAnyOrderMembersOf(MetaAnnotatedClass.class); + assertThatMembers(members).matchInAnyOrderMembersOf(MetaAnnotatedClass.class, AnnotatedClass.class); } @Test @@ -344,7 +344,7 @@ public void areNotMetaAnnotatedWith_type() { List members = filterResultOf(members().that().areDeclaredInClassesThat().areNotMetaAnnotatedWith(SomeAnnotation.class)) .on(MetaAnnotatedClass.class, AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatMembers(members).matchInAnyOrderMembersOf(AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); + assertThatMembers(members).matchInAnyOrderMembersOf(SimpleClass.class, MetaAnnotatedAnnotation.class); } @Test @@ -352,7 +352,7 @@ public void areMetaAnnotatedWith_typeName() { List members = filterResultOf(members().that().areDeclaredInClassesThat().areMetaAnnotatedWith(SomeAnnotation.class.getName())) .on(MetaAnnotatedClass.class, AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatMembers(members).matchInAnyOrderMembersOf(MetaAnnotatedClass.class); + assertThatMembers(members).matchInAnyOrderMembersOf(MetaAnnotatedClass.class, AnnotatedClass.class); } @Test @@ -360,7 +360,7 @@ public void areNotMetaAnnotatedWith_typeName() { List members = filterResultOf(members().that().areDeclaredInClassesThat().areNotMetaAnnotatedWith(SomeAnnotation.class.getName())) .on(MetaAnnotatedClass.class, AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatMembers(members).matchInAnyOrderMembersOf(AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); + assertThatMembers(members).matchInAnyOrderMembersOf(SimpleClass.class, MetaAnnotatedAnnotation.class); } @Test @@ -369,7 +369,7 @@ public void areMetaAnnotatedWith_predicate() { List members = filterResultOf(members().that().areDeclaredInClassesThat().areMetaAnnotatedWith(hasNamePredicate)) .on(MetaAnnotatedClass.class, AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatMembers(members).matchInAnyOrderMembersOf(MetaAnnotatedClass.class); + assertThatMembers(members).matchInAnyOrderMembersOf(MetaAnnotatedClass.class, AnnotatedClass.class); } @Test @@ -378,7 +378,7 @@ public void areNotMetaAnnotatedWith_predicate() { List members = filterResultOf(members().that().areDeclaredInClassesThat().areNotMetaAnnotatedWith(hasNamePredicate)) .on(MetaAnnotatedClass.class, AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatMembers(members).matchInAnyOrderMembersOf(AnnotatedClass.class, SimpleClass.class, MetaAnnotatedAnnotation.class); + assertThatMembers(members).matchInAnyOrderMembersOf(SimpleClass.class, MetaAnnotatedAnnotation.class); } @Test diff --git a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/ShouldClassesThatTest.java b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/ShouldClassesThatTest.java index 72d80b69c8..135564bbbf 100644 --- a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/ShouldClassesThatTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/ShouldClassesThatTest.java @@ -396,7 +396,7 @@ public void areMetaAnnotatedWith_type(ClassesThat noCl .on(ClassAccessingMetaAnnotatedClass.class, ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatType(getOnlyElement(classes)).matches(ClassAccessingMetaAnnotatedClass.class); + assertThatTypes(classes).matchInAnyOrder(ClassAccessingMetaAnnotatedClass.class, ClassAccessingAnnotatedClass.class); } @Test @@ -406,7 +406,7 @@ public void areNotMetaAnnotatedWith_type_access() { .on(ClassAccessingMetaAnnotatedClass.class, ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class); + assertThatTypes(classes).matchInAnyOrder(ClassAccessingSimpleClass.class); } @Test @@ -416,7 +416,7 @@ public void areNotMetaAnnotatedWith_type_dependency() { .on(ClassAccessingMetaAnnotatedClass.class, ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); + assertThatTypes(classes).matchInAnyOrder(ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); } @Test @@ -427,7 +427,7 @@ public void areMetaAnnotatedWith_typeName(ClassesThat .on(ClassAccessingMetaAnnotatedClass.class, ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatType(getOnlyElement(classes)).matches(ClassAccessingMetaAnnotatedClass.class); + assertThatTypes(classes).matchInAnyOrder(ClassAccessingMetaAnnotatedClass.class, ClassAccessingAnnotatedClass.class); } @Test @@ -437,7 +437,7 @@ public void areNotMetaAnnotatedWith_typeName_access() { .on(ClassAccessingMetaAnnotatedClass.class, ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class); + assertThatTypes(classes).matchInAnyOrder(ClassAccessingSimpleClass.class); } @Test @@ -447,7 +447,7 @@ public void areNotMetaAnnotatedWith_typeName_dependency() { .on(ClassAccessingMetaAnnotatedClass.class, ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); + assertThatTypes(classes).matchInAnyOrder(ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); } @Test @@ -459,7 +459,7 @@ public void areMetaAnnotatedWith_predicate(ClassesThat .on(ClassAccessingMetaAnnotatedClass.class, ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatType(getOnlyElement(classes)).matches(ClassAccessingMetaAnnotatedClass.class); + assertThatTypes(classes).matchInAnyOrder(ClassAccessingMetaAnnotatedClass.class, ClassAccessingAnnotatedClass.class); } @Test @@ -470,7 +470,7 @@ public void areNotMetaAnnotatedWith_predicate_access() { .on(ClassAccessingMetaAnnotatedClass.class, ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class); + assertThatTypes(classes).matchInAnyOrder(ClassAccessingSimpleClass.class); } @Test @@ -481,7 +481,7 @@ public void areNotMetaAnnotatedWith_predicate_dependency() { .on(ClassAccessingMetaAnnotatedClass.class, ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); + assertThatTypes(classes).matchInAnyOrder(ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); } @Test @@ -1210,7 +1210,7 @@ public void only_areMetaAnnotatedWith_type_access() { .on(ClassAccessingMetaAnnotatedClass.class, ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class); + assertThatTypes(classes).matchInAnyOrder(ClassAccessingSimpleClass.class); } @Test @@ -1220,7 +1220,7 @@ public void only_areMetaAnnotatedWith_type_dependency() { .on(ClassAccessingMetaAnnotatedClass.class, ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassAccessingAnnotatedClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); + assertThatTypes(classes).matchInAnyOrder(ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); } @Test @@ -1231,7 +1231,7 @@ public void only_areNotMetaAnnotatedWith_type(ClassesThat clas SimpleClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassBeingAccessedByAnnotatedClass.class, AnnotatedClass.class, - SimpleClass.class, ClassAccessingSimpleClass.class); + assertThatTypes(classes).matchInAnyOrder(SimpleClass.class, ClassAccessingSimpleClass.class); } @Test @@ -488,7 +487,9 @@ public void areNotMetaAnnotatedWith_type_access() { SimpleClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassBeingAccessedByMetaAnnotatedClass.class, MetaAnnotatedClass.class); + assertThatTypes(classes).matchInAnyOrder( + ClassBeingAccessedByMetaAnnotatedClass.class, MetaAnnotatedClass.class, + ClassBeingAccessedByAnnotatedClass.class, AnnotatedClass.class); } @Test @@ -500,7 +501,9 @@ public void areNotMetaAnnotatedWith_type_dependency() { SimpleClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassBeingAccessedByMetaAnnotatedClass.class, MetaAnnotatedClass.class, MetaAnnotatedAnnotation.class); + assertThatTypes(classes).matchInAnyOrder( + ClassBeingAccessedByMetaAnnotatedClass.class, MetaAnnotatedClass.class, MetaAnnotatedAnnotation.class, + ClassBeingAccessedByAnnotatedClass.class, AnnotatedClass.class); } @Test @@ -513,8 +516,7 @@ public void areMetaAnnotatedWith_typeName(ClassesThat SimpleClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassBeingAccessedByAnnotatedClass.class, AnnotatedClass.class, - SimpleClass.class, ClassAccessingSimpleClass.class); + assertThatTypes(classes).matchInAnyOrder(SimpleClass.class, ClassAccessingSimpleClass.class); } @Test @@ -526,7 +528,9 @@ public void areNotMetaAnnotatedWith_typeName_access() { SimpleClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassBeingAccessedByMetaAnnotatedClass.class, MetaAnnotatedClass.class); + assertThatTypes(classes).matchInAnyOrder( + ClassBeingAccessedByMetaAnnotatedClass.class, MetaAnnotatedClass.class, + ClassBeingAccessedByAnnotatedClass.class, AnnotatedClass.class); } @Test @@ -538,7 +542,9 @@ public void areNotMetaAnnotatedWith_typeName_dependency() { SimpleClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassBeingAccessedByMetaAnnotatedClass.class, MetaAnnotatedClass.class, MetaAnnotatedAnnotation.class); + assertThatTypes(classes).matchInAnyOrder( + ClassBeingAccessedByMetaAnnotatedClass.class, MetaAnnotatedClass.class, MetaAnnotatedAnnotation.class, + ClassBeingAccessedByAnnotatedClass.class, AnnotatedClass.class); } @Test @@ -552,8 +558,7 @@ public void areMetaAnnotatedWith_predicate(ClassesThat SimpleClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassBeingAccessedByAnnotatedClass.class, AnnotatedClass.class, - SimpleClass.class, ClassAccessingSimpleClass.class); + assertThatTypes(classes).matchInAnyOrder(SimpleClass.class, ClassAccessingSimpleClass.class); } @Test @@ -566,7 +571,9 @@ public void areNotMetaAnnotatedWith_predicate_access() { SimpleClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassBeingAccessedByMetaAnnotatedClass.class, MetaAnnotatedClass.class); + assertThatTypes(classes).matchInAnyOrder( + ClassBeingAccessedByMetaAnnotatedClass.class, MetaAnnotatedClass.class, + ClassBeingAccessedByAnnotatedClass.class, AnnotatedClass.class); } @Test @@ -579,7 +586,9 @@ public void areNotMetaAnnotatedWith_predicate_dependency() { SimpleClass.class, ClassAccessingSimpleClass.class, MetaAnnotatedAnnotation.class); - assertThatTypes(classes).matchInAnyOrder(ClassBeingAccessedByMetaAnnotatedClass.class, MetaAnnotatedClass.class, MetaAnnotatedAnnotation.class); + assertThatTypes(classes).matchInAnyOrder( + ClassBeingAccessedByMetaAnnotatedClass.class, MetaAnnotatedClass.class, MetaAnnotatedAnnotation.class, + ClassBeingAccessedByAnnotatedClass.class, AnnotatedClass.class); } @Test From 71835ef92dd0e0ab2849e6e1ec898be15756b041 Mon Sep 17 00:00:00 2001 From: Peter Gafert Date: Sun, 21 Feb 2021 15:40:51 +0100 Subject: [PATCH 2/2] add tests for `classes().should().{be/notBe}MetaAnnotatedWith(..)` It seems like these tests have been forgotten. Luckily almost all the logic is already tested in `MembersShouldTest`, except for delegating one-liners, nevertheless I've added the correct tests now in `ClassesShouldTest`. Signed-off-by: Peter Gafert --- .../syntax/elements/ClassesShouldTest.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/ClassesShouldTest.java b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/ClassesShouldTest.java index ef324bfba9..e671fffebb 100644 --- a/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/ClassesShouldTest.java +++ b/archunit/src/test/java/com/tngtech/archunit/lang/syntax/elements/ClassesShouldTest.java @@ -676,6 +676,68 @@ public void notAnnotatedWith(ArchRule rule, Class correctClass, Class wron .doesNotMatch(String.format(".*<%s>.*annotated.*", quote(correctClass.getName()))); } + @DataProvider + public static Object[][] metaAnnotated_rules() { + return $$( + $(classes().should().beMetaAnnotatedWith(SomeMetaAnnotation.class), + SomeAnnotatedClass.class, String.class), + $(classes().should(ArchConditions.beMetaAnnotatedWith(SomeMetaAnnotation.class)), + SomeAnnotatedClass.class, String.class), + $(classes().should().beMetaAnnotatedWith(SomeMetaAnnotation.class.getName()), + SomeAnnotatedClass.class, String.class), + $(classes().should(ArchConditions.beMetaAnnotatedWith(SomeMetaAnnotation.class.getName())), + SomeAnnotatedClass.class, String.class), + $(classes().should().beMetaAnnotatedWith(annotation(SomeMetaAnnotation.class)), + SomeAnnotatedClass.class, String.class), + $(classes().should(ArchConditions.beMetaAnnotatedWith(annotation(SomeMetaAnnotation.class))), + SomeAnnotatedClass.class, String.class)); + } + + @Test + @UseDataProvider("metaAnnotated_rules") + public void metaAnnotatedWith(ArchRule rule, Class correctClass, Class wrongClass) { + EvaluationResult result = rule.evaluate(importClasses(correctClass, wrongClass)); + + assertThat(singleLineFailureReportOf(result)) + .contains(String.format("classes should be meta-annotated with @%s", SomeMetaAnnotation.class.getSimpleName())) + .containsPattern(String.format("Class <%s> is not meta-annotated with @%s in %s", + quote(wrongClass.getName()), + SomeMetaAnnotation.class.getSimpleName(), + locationPattern(String.class))) + .doesNotMatch(String.format(".*<%s>.*meta-annotated.*", quote(correctClass.getName()))); + } + + @DataProvider + public static Object[][] notMetaAnnotated_rules() { + return $$( + $(classes().should().notBeMetaAnnotatedWith(SomeMetaAnnotation.class), + String.class, SomeAnnotatedClass.class), + $(classes().should(ArchConditions.notBeMetaAnnotatedWith(SomeMetaAnnotation.class)), + String.class, SomeAnnotatedClass.class), + $(classes().should().notBeMetaAnnotatedWith(SomeMetaAnnotation.class.getName()), + String.class, SomeAnnotatedClass.class), + $(classes().should(ArchConditions.notBeMetaAnnotatedWith(SomeMetaAnnotation.class.getName())), + String.class, SomeAnnotatedClass.class), + $(classes().should().notBeMetaAnnotatedWith(annotation(SomeMetaAnnotation.class)), + String.class, SomeAnnotatedClass.class), + $(classes().should(ArchConditions.notBeMetaAnnotatedWith(annotation(SomeMetaAnnotation.class))), + String.class, SomeAnnotatedClass.class)); + } + + @Test + @UseDataProvider("notMetaAnnotated_rules") + public void notMetaAnnotatedWith(ArchRule rule, Class correctClass, Class wrongClass) { + EvaluationResult result = rule.evaluate(importClasses(correctClass, wrongClass)); + + assertThat(singleLineFailureReportOf(result)) + .contains("classes should not be meta-annotated with @" + SomeMetaAnnotation.class.getSimpleName()) + .containsPattern(String.format("Class <%s> is meta-annotated with @%s in %s", + quote(wrongClass.getName()), + SomeMetaAnnotation.class.getSimpleName(), + locationPattern(getClass()))) + .doesNotMatch(String.format(".*<%s>.*meta-annotated.*", quote(correctClass.getName()))); + } + /** * Compare {@link CanBeAnnotatedTest#annotatedWith_Retention_Source_is_rejected} */ @@ -1971,10 +2033,18 @@ static class PackagePrivateClass { private static class PrivateClass { } + @SomeAnnotation @RuntimeRetentionAnnotation private static class SomeAnnotatedClass { } + @interface SomeMetaAnnotation { + } + + @SomeMetaAnnotation + @interface SomeAnnotation { + } + private static class NestedClassWithSomeMoreClasses { static class StaticNestedClass {