Skip to content

Commit 9c6dd1f

Browse files
committed
Polishing.
Refactor DisabledOnHibernate61/62 annotation to DisabledOnHibernate with a version string.
1 parent 4148307 commit 9c6dd1f

10 files changed

+249
-112
lines changed

spring-data-jpa/src/test/java/org/springframework/data/jpa/AntlrVersionTests.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@
2323
import org.antlr.v4.runtime.RuntimeMetaData;
2424
import org.hibernate.grammars.hql.HqlParser;
2525
import org.junit.jupiter.api.Test;
26+
2627
import org.springframework.asm.ClassReader;
2728
import org.springframework.asm.ClassVisitor;
2829
import org.springframework.asm.MethodVisitor;
2930
import org.springframework.asm.Opcodes;
30-
import org.springframework.data.jpa.util.DisabledOnHibernate62;
31+
import org.springframework.data.jpa.util.DisabledOnHibernate;
3132
import org.springframework.lang.Nullable;
3233

3334
/**
@@ -41,7 +42,7 @@
4142
class AntlrVersionTests {
4243

4344
@Test
44-
@DisabledOnHibernate62
45+
@DisabledOnHibernate("6.2")
4546
void antlrVersionConvergence() throws Exception {
4647

4748
ClassReader reader = new ClassReader(HqlParser.class.getName());

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/procedures/PostgresStoredProcedureIntegrationTests.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
import org.springframework.data.jpa.repository.JpaRepository;
4343
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
4444
import org.springframework.data.jpa.repository.query.Procedure;
45-
import org.springframework.data.jpa.util.DisabledOnHibernate62;
45+
import org.springframework.data.jpa.util.DisabledOnHibernate;
4646
import org.springframework.test.context.ContextConfiguration;
4747
import org.springframework.test.context.junit.jupiter.SpringExtension;
4848
import org.springframework.transaction.annotation.EnableTransactionManagement;
@@ -106,7 +106,7 @@ void testNamedOutputParameter() {
106106
new Employee(4, "Gabriel"));
107107
}
108108

109-
@DisabledOnHibernate62
109+
@DisabledOnHibernate("6")
110110
@Test // 2256
111111
void testSingleEntityFromResultSet() {
112112

@@ -160,6 +160,8 @@ void supportsMultipleOutParameters() {
160160
}
161161

162162
@Test // GH-3081
163+
@DisabledOnHibernate(value = "6.2",
164+
disabledReason = "Hibernate 6.2 does not support stored procedures with array types")
163165
void supportsArrayTypes() {
164166

165167
String result = repository.accept_array(new String[] { "one", "two" });

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/procedures/PostgresStoredProcedureNullHandlingIntegrationTests.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
import org.springframework.data.jpa.repository.Temporal;
3737
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
3838
import org.springframework.data.jpa.repository.query.Procedure;
39-
import org.springframework.data.jpa.util.DisabledOnHibernate61;
39+
import org.springframework.data.jpa.util.DisabledOnHibernate;
4040
import org.springframework.test.context.ContextConfiguration;
4141
import org.springframework.test.context.junit.jupiter.SpringExtension;
4242
import org.springframework.transaction.annotation.EnableTransactionManagement;
@@ -49,7 +49,7 @@
4949
*
5050
* @author Greg Turnquist
5151
*/
52-
@DisabledOnHibernate61 // GH-2903
52+
@DisabledOnHibernate("6.1") // GH-2903
5353
@Transactional
5454
@ExtendWith(SpringExtension.class)
5555
@ContextConfiguration(classes = PostgresStoredProcedureNullHandlingIntegrationTests.Config.class)

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/HibernateJpaMetamodelEntityInformationIntegrationTests.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717

1818
import org.junit.jupiter.api.Test;
1919
import org.junit.jupiter.api.extension.ExtendWith;
20-
import org.springframework.data.jpa.util.DisabledOnHibernate61;
20+
21+
import org.springframework.data.jpa.util.DisabledOnHibernate;
2122
import org.springframework.test.context.ContextConfiguration;
2223
import org.springframework.test.context.junit.jupiter.SpringExtension;
2324

@@ -35,21 +36,21 @@ String getMetadadataPersistenceUnitName() {
3536
return "metadata-id-handling";
3637
}
3738

38-
@DisabledOnHibernate61
39+
@DisabledOnHibernate("6.1")
3940
@Test
4041
@Override
4142
void correctlyDeterminesIdValueForNestedIdClassesWithNonPrimitiveNonManagedType() {
4243
super.correctlyDeterminesIdValueForNestedIdClassesWithNonPrimitiveNonManagedType();
4344
}
4445

45-
@DisabledOnHibernate61
46+
@DisabledOnHibernate("6.1")
4647
@Test
4748
@Override
4849
void prefersPrivateGetterOverFieldAccess() {
4950
super.prefersPrivateGetterOverFieldAccess();
5051
}
5152

52-
@DisabledOnHibernate61
53+
@DisabledOnHibernate("6.1")
5354
@Test
5455
@Override
5556
void findsIdClassOnMappedSuperclass() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.jpa.util;
17+
18+
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.*;
19+
import static org.junit.platform.commons.util.AnnotationUtils.*;
20+
21+
import java.lang.annotation.Annotation;
22+
import java.util.function.Function;
23+
24+
import org.junit.jupiter.api.extension.ConditionEvaluationResult;
25+
import org.junit.jupiter.api.extension.ExecutionCondition;
26+
import org.junit.jupiter.api.extension.ExtensionContext;
27+
28+
abstract class BooleanExecutionCondition<A extends Annotation> implements ExecutionCondition {
29+
30+
private final Class<A> annotationType;
31+
private final String enabledReason;
32+
private final String disabledReason;
33+
private final Function<A, String> customDisabledReason;
34+
35+
BooleanExecutionCondition(Class<A> annotationType, String enabledReason, String disabledReason,
36+
Function<A, String> customDisabledReason) {
37+
this.annotationType = annotationType;
38+
this.enabledReason = enabledReason;
39+
this.disabledReason = disabledReason;
40+
this.customDisabledReason = customDisabledReason;
41+
}
42+
43+
abstract boolean isEnabled(A annotation);
44+
45+
@Override
46+
public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) {
47+
return findAnnotation(context.getElement(), annotationType) //
48+
.map(annotation -> isEnabled(annotation) ? enabled(enabledReason)
49+
: disabled(disabledReason, customDisabledReason.apply(annotation))) //
50+
.orElseGet(this::enabledByDefault);
51+
}
52+
53+
private ConditionEvaluationResult enabledByDefault() {
54+
String reason = String.format("@%s is not present", annotationType.getSimpleName());
55+
return enabled(reason);
56+
}
57+
58+
}

spring-data-jpa/src/test/java/org/springframework/data/jpa/util/DisabledOnHibernate61.java renamed to spring-data-jpa/src/test/java/org/springframework/data/jpa/util/DisabledOnHibernate.java

+21-4
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,31 @@
2323
import org.junit.jupiter.api.extension.ExtendWith;
2424

2525
/**
26-
* Annotation to flag JUnit 5 test cases to ONLY activate when Hibernate 6.2 is on the classpath.
26+
* {@code @DisabledOnHibernate} is used to signal that the annotated test class or test method is only <em>disabled</em>
27+
* if the given Hibernate {@linkplain #value version} is being used.
2728
*
2829
* @author Greg Turnquist
29-
* @since 3.1
30+
* @author Mark Paluch
31+
* @since 3.2
3032
*/
3133
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.ANNOTATION_TYPE })
3234
@Retention(RetentionPolicy.RUNTIME)
33-
@ExtendWith(HibernateSupport.DisabledWhenHibernate61OnClasspath.class)
34-
public @interface DisabledOnHibernate61 {
35+
@ExtendWith(DisabledOnHibernateCondition.class)
36+
public @interface DisabledOnHibernate {
3537

38+
/**
39+
* The version of Hibernate to disable the test or container case on. The version specifier can hold individual
40+
* version components matching effectively the version in a prefix-manner. The more specific you want to match, the
41+
* more version components you can specify, such as {@code 6.2.1} to match a specific service release or {@code 6} to
42+
* match a full major version.
43+
*/
44+
String value();
45+
46+
/**
47+
* Custom reason to provide if the test or container is disabled.
48+
* <p>
49+
* If a custom reason is supplied, it will be combined with the default reason for this annotation. If a custom reason
50+
* is not supplied, the default reason will be used.
51+
*/
52+
String disabledReason() default "";
3653
}

spring-data-jpa/src/test/java/org/springframework/data/jpa/util/DisabledOnHibernate62.java

-36
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.jpa.util;
17+
18+
import java.util.ArrayList;
19+
import java.util.List;
20+
import java.util.regex.Matcher;
21+
import java.util.regex.Pattern;
22+
23+
import org.junit.jupiter.api.extension.ExecutionCondition;
24+
25+
/**
26+
* {@link ExecutionCondition} for {@link DisabledOnHibernate @DisabledOnHibernate}.
27+
*
28+
* @see DisabledOnHibernate
29+
*/
30+
class DisabledOnHibernateCondition extends BooleanExecutionCondition<DisabledOnHibernate> {
31+
32+
static final String ENABLED_ON_CURRENT_HIBERNATE = //
33+
"Enabled on Hibernate version: " + org.hibernate.Version.getVersionString();
34+
35+
static final String DISABLED_ON_CURRENT_HIBERNATE = //
36+
"Disabled on Hibernate version: " + org.hibernate.Version.getVersionString();
37+
38+
DisabledOnHibernateCondition() {
39+
super(DisabledOnHibernate.class, ENABLED_ON_CURRENT_HIBERNATE, DISABLED_ON_CURRENT_HIBERNATE,
40+
DisabledOnHibernate::disabledReason);
41+
}
42+
43+
@Override
44+
boolean isEnabled(DisabledOnHibernate annotation) {
45+
46+
VersionMatcher disabled = VersionMatcher.parse(annotation.value());
47+
VersionMatcher hibernate = VersionMatcher.parse(org.hibernate.Version.getVersionString());
48+
49+
return !disabled.matches(hibernate);
50+
}
51+
52+
static class VersionMatcher {
53+
54+
private static final Pattern PATTERN = Pattern.compile("(\\d+)+");
55+
private final int[] components;
56+
57+
private VersionMatcher(int[] components) {
58+
this.components = components;
59+
}
60+
61+
/**
62+
* Parse the given version string into a {@link VersionMatcher}.
63+
*
64+
* @param version
65+
* @return
66+
*/
67+
public static VersionMatcher parse(String version) {
68+
69+
Matcher matcher = PATTERN.matcher(version);
70+
List<Integer> ints = new ArrayList<>();
71+
while (matcher.find()) {
72+
ints.add(Integer.parseInt(matcher.group()));
73+
}
74+
75+
return new VersionMatcher(ints.stream().mapToInt(value -> value).toArray());
76+
}
77+
78+
/**
79+
* Match the given version against another VersionMatcher. This matcher's version spec controls the expected length.
80+
* If the other version is shorter, then the match returns {@code false}.
81+
*
82+
* @param version
83+
* @return
84+
*/
85+
public boolean matches(VersionMatcher version) {
86+
87+
for (int i = 0; i < components.length; i++) {
88+
if (version.components.length <= i) {
89+
return false;
90+
}
91+
if (components[i] != version.components[i]) {
92+
return false;
93+
}
94+
}
95+
96+
return true;
97+
}
98+
}
99+
100+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.jpa.util;
17+
18+
import static org.assertj.core.api.Assertions.*;
19+
import static org.springframework.data.jpa.util.DisabledOnHibernateCondition.*;
20+
21+
import org.junit.jupiter.api.Test;
22+
23+
/**
24+
* Unit tests for {@link DisabledOnHibernate}.
25+
*
26+
* @author Mark Paluch
27+
*/
28+
class DisabledOnHibernateConditionTests {
29+
30+
@Test // GH-3081
31+
void shouldMatchVersions() {
32+
33+
VersionMatcher spec = VersionMatcher.parse("1.2");
34+
VersionMatcher lib = VersionMatcher.parse("v1.2.3.4.Final");
35+
36+
assertThat(spec.matches(lib)).isTrue();
37+
}
38+
39+
@Test // GH-3081
40+
void shouldNotMatchVersions() {
41+
42+
VersionMatcher spec = VersionMatcher.parse("1.2");
43+
VersionMatcher lib = VersionMatcher.parse("2.2.3.4");
44+
45+
assertThat(spec.matches(lib)).isFalse();
46+
}
47+
48+
@Test // GH-3081
49+
void shouldNotMatchVersionsWithExceedingLength() {
50+
51+
VersionMatcher spec = VersionMatcher.parse("1.2.3.4");
52+
VersionMatcher lib = VersionMatcher.parse("1.2");
53+
54+
assertThat(spec.matches(lib)).isFalse();
55+
}
56+
}

0 commit comments

Comments
 (0)