Skip to content

Commit 7273cf4

Browse files
committed
create annotations to replace DBSelectionExtension features
1 parent f9ea159 commit 7273cf4

File tree

6 files changed

+470
-0
lines changed

6 files changed

+470
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.reactive.annotations;
7+
8+
import java.lang.annotation.Annotation;
9+
import java.lang.reflect.AnnotatedElement;
10+
import java.util.Collection;
11+
import java.util.Collections;
12+
import java.util.LinkedHashMap;
13+
14+
import org.hibernate.reactive.containers.DatabaseConfiguration;
15+
16+
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
17+
import org.junit.jupiter.api.extension.ExecutionCondition;
18+
import org.junit.jupiter.api.extension.ExtensionContext;
19+
20+
import org.jboss.logging.Logger;
21+
22+
23+
public class DBTypeFilterExtension implements ExecutionCondition {
24+
private static final Logger LOG = Logger.getLogger( DBTypeFilterExtension.class );
25+
26+
@Override
27+
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
28+
// Tests are run on a single DB, so capture the current DB being tested.
29+
final DatabaseConfiguration.DBType dbType = DatabaseConfiguration.dbType();
30+
if ( dbType == null ) {
31+
throw new RuntimeException( "#getDbType() returned null" );
32+
}
33+
34+
LOG.info( "Checking DBType [" + dbType + "] - context = " + context.getDisplayName() );
35+
36+
ConditionEvaluationResult enableResult = evaluateEnableConditions( context, dbType );
37+
if( enableResult == null ) {
38+
return evaluateDisableConditions( context, dbType );
39+
}
40+
if( enableResult.isDisabled() ) {
41+
LOG.info( enableResult.getReason() );
42+
}
43+
return enableResult;
44+
}
45+
46+
private ConditionEvaluationResult evaluateDisableConditions(ExtensionContext context, DatabaseConfiguration.DBType dbType) {
47+
final Collection<DisableFor> disabledDBTypesList = collectAnnotations(
48+
context,
49+
DisableFor.class,
50+
DisableForGroup.class,
51+
(methodAnnotation, methodAnnotations, classAnnotation, classAnnotations) -> {
52+
final LinkedHashMap<DatabaseConfiguration.DBType, DisableFor> map = new LinkedHashMap<>();
53+
if ( classAnnotation != null ) {
54+
map.put( classAnnotation.value(), classAnnotation );
55+
}
56+
if ( classAnnotations != null ) {
57+
for ( DisableFor annotation : classAnnotations ) {
58+
map.put( annotation.value(), annotation );
59+
}
60+
}
61+
if ( methodAnnotation != null ) {
62+
map.put( methodAnnotation.value(), methodAnnotation );
63+
}
64+
if ( methodAnnotations != null ) {
65+
for ( DisableFor annotation : methodAnnotations ) {
66+
map.put( annotation.value(), annotation );
67+
}
68+
}
69+
return map.values();
70+
}
71+
);
72+
73+
for ( DisableFor disableForDBType : disabledDBTypesList ) {
74+
DatabaseConfiguration.DBType currentDbType = disableForDBType.value();
75+
if ( dbType == currentDbType ) {
76+
String skipMessage = " Skipping test for DB: " + dbType.toString() +
77+
" REASON: " + disableForDBType.reason();
78+
LOG.info( skipMessage );
79+
return ConditionEvaluationResult.disabled( skipMessage );
80+
}
81+
}
82+
83+
LOG.info(" Enabling test for DB: " + dbType.toString() );
84+
return ConditionEvaluationResult.enabled( "" );
85+
}
86+
87+
private ConditionEvaluationResult evaluateEnableConditions(ExtensionContext context, DatabaseConfiguration.DBType dbType) {
88+
final Collection<EnableFor> enabledDBTypesList = collectAnnotations(
89+
context,
90+
EnableFor.class,
91+
EnableForGroup.class,
92+
(methodAnnotation, methodAnnotations, classAnnotation, classAnnotations) -> {
93+
final LinkedHashMap<DatabaseConfiguration.DBType, EnableFor> map = new LinkedHashMap<>();
94+
if ( classAnnotation != null ) {
95+
map.put( classAnnotation.value(), classAnnotation );
96+
}
97+
if ( classAnnotations != null ) {
98+
for ( EnableFor annotation : classAnnotations ) {
99+
map.put( annotation.value(), annotation );
100+
}
101+
}
102+
if ( methodAnnotation != null ) {
103+
map.put( methodAnnotation.value(), methodAnnotation );
104+
}
105+
if ( methodAnnotations != null ) {
106+
for ( EnableFor annotation : methodAnnotations ) {
107+
map.put( annotation.value(), annotation );
108+
}
109+
}
110+
return map.values();
111+
}
112+
);
113+
114+
if( !enabledDBTypesList.isEmpty() ) {
115+
for ( EnableFor enableForDBType : enabledDBTypesList ) {
116+
DatabaseConfiguration.DBType currentDbType = enableForDBType.value();
117+
if( dbType == currentDbType ) {
118+
LOG.info(" Enabling test for DB: " + dbType.toString() );
119+
return ConditionEvaluationResult.enabled( "" );
120+
}
121+
}
122+
return ConditionEvaluationResult.disabled( getMessageForNotAnEnabledDBType(enabledDBTypesList) );
123+
}
124+
return null;
125+
}
126+
127+
private String getMessageForNotAnEnabledDBType(Collection<EnableFor> allowedDBTypes) {
128+
StringBuilder sb = new StringBuilder();
129+
sb.append( "The test method or test class currently supports only these DBTypes: [ ");
130+
int i=1;
131+
for ( EnableFor enableForDBType : allowedDBTypes ) {
132+
DatabaseConfiguration.DBType currentDbType = enableForDBType.value();
133+
sb.append( currentDbType.toString() );
134+
if( i++ < allowedDBTypes.size() ) {
135+
sb.append(", ");
136+
}
137+
138+
}
139+
sb.append(" ] ");
140+
return sb.toString();
141+
}
142+
143+
private static <A extends Annotation> Collection<A> collectAnnotations(
144+
ExtensionContext context,
145+
Class<A> annotationType,
146+
Class<? extends Annotation> groupAnnotationType,
147+
TestAnnotationCollector<A> collector) {
148+
if ( !context.getElement().isPresent() ) {
149+
return Collections.emptyList();
150+
}
151+
152+
final AnnotatedElement annotatedElement = context.getElement().get();
153+
final A methodAnnotation = annotatedElement.getAnnotation( annotationType );
154+
final A classAnnotation = context.getTestInstance().map( i -> i.getClass().getAnnotation( annotationType ) ).orElse( null );
155+
final Annotation methodPluralAnn = annotatedElement.getAnnotation( groupAnnotationType );
156+
final Annotation classPluralAnn = context.getTestInstance().map( i -> i.getClass().getAnnotation( groupAnnotationType ) ).orElse( null );
157+
final A[] methodAnnotations;
158+
final A[] classAnnotations;
159+
if ( methodPluralAnn != null ) {
160+
try {
161+
methodAnnotations = (A[]) groupAnnotationType.getDeclaredMethod( "value", null ).invoke( methodPluralAnn );
162+
}
163+
catch (Exception e) {
164+
throw new RuntimeException( e );
165+
}
166+
}
167+
else {
168+
methodAnnotations = null;
169+
}
170+
if ( classPluralAnn != null ) {
171+
try {
172+
classAnnotations = (A[]) groupAnnotationType.getDeclaredMethod( "value", null ).invoke( classPluralAnn );
173+
}
174+
catch (Exception e) {
175+
throw new RuntimeException( e );
176+
}
177+
}
178+
else {
179+
classAnnotations = null;
180+
}
181+
182+
return collector.collect( methodAnnotation, methodAnnotations, classAnnotation, classAnnotations );
183+
}
184+
185+
public interface TestAnnotationCollector<S> {
186+
Collection<S> collect(S methodAnnotation, S[] methodAnnotations, S classAnnotation, S[] classAnnotations);
187+
}
188+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.reactive.annotations;
7+
8+
import java.lang.annotation.ElementType;
9+
import java.lang.annotation.Inherited;
10+
import java.lang.annotation.Repeatable;
11+
import java.lang.annotation.Retention;
12+
import java.lang.annotation.RetentionPolicy;
13+
import java.lang.annotation.Target;
14+
15+
import org.hibernate.reactive.containers.DatabaseConfiguration;
16+
17+
import org.junit.jupiter.api.extension.ExtendWith;
18+
19+
/**
20+
* Annotation that allows disabling tests or test methods for specific database types.
21+
* <p>
22+
* Types are defined in {@link DatabaseConfiguration.DBType} and can be
23+
* applied to a test class or a test method
24+
*
25+
* <pre>{@code
26+
*
27+
* @DisableFor( value = MYSQL, reason = "Reason #1")
28+
* public class DisableDBForClassTest {
29+
*
30+
* @Test
31+
* public void test(VertxTestContext context) {
32+
* ....
33+
* }
34+
* }
35+
*
36+
* public class DisableDBForMethodTest {
37+
*
38+
* @Test
39+
* @DisableFor( value = POSTGRES, reason = "Reason #2")
40+
* public void test(VertxTestContext context) {
41+
* ....
42+
* }
43+
* }
44+
* }</pre>
45+
*
46+
*
47+
* This annotation was based off of ORM's similar solution for Dialects:
48+
* @see org.hibernate.testing.orm.junit.SkipForDialect.java
49+
*/
50+
51+
@SuppressWarnings("JavadocReference")
52+
@Inherited
53+
@Retention( RetentionPolicy.RUNTIME )
54+
@Target({ ElementType.TYPE, ElementType.METHOD})
55+
@Repeatable( DisableForGroup.class )
56+
57+
@ExtendWith( DBTypeFilterExtension.class )
58+
public @interface DisableFor {
59+
DatabaseConfiguration.DBType value();
60+
String reason() default "<undefined>";
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.reactive.annotations;
7+
8+
import java.lang.annotation.ElementType;
9+
import java.lang.annotation.Inherited;
10+
import java.lang.annotation.Retention;
11+
import java.lang.annotation.RetentionPolicy;
12+
import java.lang.annotation.Target;
13+
14+
import org.hibernate.reactive.containers.DatabaseConfiguration;
15+
16+
import org.junit.jupiter.api.extension.ExtendWith;
17+
18+
/**
19+
* Annotation that allows disabling tests or test methods for specific database types.
20+
*
21+
* Types are defined in {@link DatabaseConfiguration.DBType} and can be
22+
* applied to a test class or a test method
23+
*
24+
* <pre>{@code
25+
*
26+
* @DisableForGroup( {
27+
* @DisableFor(value = MYSQL, reason = "Reason #1"),
28+
* @DisableFor(value = DB2, reason = "Reason #2")
29+
* } )
30+
* public class DisableDBsForClassTest {
31+
*
32+
* @Test
33+
* public void test(VertxTestContext context) {
34+
* ....
35+
* }
36+
* }
37+
*
38+
* public class DisableDBsForMethodTest {
39+
*
40+
* @Test
41+
* @DisableForGroup( {
42+
* @DisableFor(value = POSTGRES, reason = "Reason #3"),
43+
* @DisableFor(value = MYSQL, reason = "Reason #4")
44+
* } )
45+
* public void test(VertxTestContext context) {
46+
* ....
47+
* }
48+
* }
49+
* }</pre>
50+
*
51+
*
52+
* This annotation was based off of ORM's similar solution for Dialects:
53+
* @see org.hibernate.testing.orm.junit.SkipForDialects.java
54+
*/
55+
@Inherited
56+
@Retention(RetentionPolicy.RUNTIME)
57+
@Target({ ElementType.TYPE, ElementType.METHOD})
58+
59+
@ExtendWith( DBTypeFilterExtension.class )
60+
public @interface DisableForGroup {
61+
DisableFor[] value();
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/* Hibernate, Relational Persistence for Idiomatic Java
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
* Copyright: Red Hat Inc. and Hibernate Authors
5+
*/
6+
package org.hibernate.reactive.annotations;
7+
8+
import java.lang.annotation.ElementType;
9+
import java.lang.annotation.Inherited;
10+
import java.lang.annotation.Repeatable;
11+
import java.lang.annotation.Retention;
12+
import java.lang.annotation.RetentionPolicy;
13+
import java.lang.annotation.Target;
14+
15+
import org.hibernate.reactive.containers.DatabaseConfiguration;
16+
17+
import org.junit.jupiter.api.extension.ExtendWith;
18+
19+
/**
20+
* Annotation that allows disabling tests or test methods only for specific database types.
21+
* <p>
22+
* Types are defined in {@link DatabaseConfiguration.DBType} and can be
23+
* applied to a test class or a test method
24+
*
25+
* <pre>{@code
26+
*
27+
* @EnableFor( MYSQL )
28+
* public class EnableDBForClassTest {
29+
*
30+
* @Test
31+
* public void test(VertxTestContext context) {
32+
* ....
33+
* }
34+
* }
35+
*
36+
* public class EnableDBForMethodTest {
37+
*
38+
* @Test
39+
* @EnableFor( POSTGRES )
40+
* public void test(VertxTestContext context) {
41+
* ....
42+
* }
43+
* }
44+
* }</pre>
45+
*
46+
*
47+
* This annotation was based off of ORM's similar solution for Dialects:
48+
* @see org.hibernate.testing.orm.junit.SkipForDialect.java
49+
*/
50+
51+
@SuppressWarnings("JavadocReference")
52+
@Inherited
53+
@Retention( RetentionPolicy.RUNTIME )
54+
@Target({ ElementType.TYPE, ElementType.METHOD})
55+
@Repeatable( EnableForGroup.class )
56+
57+
@ExtendWith( DBTypeFilterExtension.class )
58+
public @interface EnableFor {
59+
DatabaseConfiguration.DBType value();
60+
}

0 commit comments

Comments
 (0)