You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by ma...@apache.org on 2026/02/25 14:23:29 UTC
(grails-core) branch database-cleanup-feature-feedback created (now 3dfc3d6544)
This is an automated email from the ASF dual-hosted git repository.
matrei pushed a change to branch database-cleanup-feature-feedback
in repository https://gitbox.apache.org/repos/asf/grails-core.git
at 3dfc3d6544 refactor: rename to `grails-testing-support-dbcleanup-*`
This branch includes the following new commits:
new 588eab185a style: groovy cleanup
new 3dfc3d6544 refactor: rename to `grails-testing-support-dbcleanup-*`
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(grails-core) 01/02: style: groovy cleanup
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
matrei pushed a commit to branch database-cleanup-feature-feedback
in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit 588eab185a2439216bef146e70719cd088afa0eb
Author: Mattias Reichel <ma...@gmail.com>
AuthorDate: Wed Feb 25 15:14:30 2026 +0100
style: groovy cleanup
---
.../cleanup/core/ApplicationContextResolver.groovy | 1 -
.../testing/cleanup/core/DatabaseCleaner.groovy | 35 ++++-
.../testing/cleanup/core/DatabaseCleanup.groovy | 3 +-
.../cleanup/core/DatabaseCleanupContext.groovy | 149 +++++++++++++--------
.../cleanup/core/DatabaseCleanupExtension.groovy | 82 ++++++------
.../cleanup/core/DatabaseCleanupInterceptor.groovy | 73 ++++++----
.../cleanup/core/DatabaseCleanupStats.groovy | 16 +--
.../cleanup/core/DatasourceCleanupMapping.groovy | 68 +++++-----
.../core/DefaultApplicationContextResolver.groovy | 11 +-
.../cleanup/core/TestContextHolderListener.groovy | 1 -
.../testing/cleanup/h2/H2DatabaseCleaner.groovy | 60 +++------
.../cleanup/h2/H2DatabaseCleanupHelper.groovy | 97 +++++---------
.../postgresql/PostgresDatabaseCleaner.groovy | 90 ++++---------
.../PostgresDatabaseCleanupHelper.groovy | 74 ++++------
14 files changed, 363 insertions(+), 397 deletions(-)
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/ApplicationContextResolver.groovy b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/ApplicationContextResolver.groovy
index d367da4e2c..45fff9d4a0 100644
--- a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/ApplicationContextResolver.groovy
+++ b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/ApplicationContextResolver.groovy
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.grails.testing.cleanup.core
import groovy.transform.CompileStatic
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleaner.groovy b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleaner.groovy
index 3b35214b24..5329039153 100644
--- a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleaner.groovy
+++ b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleaner.groovy
@@ -16,14 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.grails.testing.cleanup.core
import javax.sql.DataSource
import groovy.transform.CompileStatic
+import org.codehaus.groovy.runtime.InvokerHelper
import org.springframework.context.ApplicationContext
+import org.springframework.util.ClassUtils
/**
* SPI interface for database-specific cleanup implementations.
@@ -37,16 +38,16 @@ import org.springframework.context.ApplicationContext
* {@code META-INF/services/org.apache.grails.testing.cleanup.core.DatabaseCleaner}.</p>
*/
@CompileStatic
-interface DatabaseCleaner {
+trait DatabaseCleaner {
/**
* Returns the database type that this cleaner supports (e.g., {@code "h2"}, {@code "mysql"},
- * {@code "postgresql"}). This value is used to match cleaners to datasources at runtime and
+ * {@code "postgresql"}). This value is used to match cleaners to data sources at runtime and
* must be unique across all {@link DatabaseCleaner} implementations on the classpath.
*
* @return a non-null, non-empty string identifying the database type
*/
- String databaseType()
+ abstract String databaseType()
/**
* Returns {@code true} if this cleaner supports the given {@link DataSource}.
@@ -55,7 +56,7 @@ interface DatabaseCleaner {
* @param dataSource the datasource to check
* @return {@code true} if this cleaner can handle the given datasource
*/
- boolean supports(DataSource dataSource)
+ abstract boolean supports(DataSource dataSource)
/**
* Performs the cleanup (truncation) of all tables in the given datasource.
@@ -64,5 +65,27 @@ interface DatabaseCleaner {
* @param dataSource the datasource to clean
* @return statistics about what was cleaned
*/
- DatabaseCleanupStats cleanup(ApplicationContext applicationContext, DataSource dataSource)
+ abstract DatabaseCleanupStats cleanup(ApplicationContext applicationContext, DataSource dataSource)
+
+ /**
+ * Optional callback to evict the Hibernate second-level cache after database cleanup.
+ * This is necessary for tests that rely on Hibernate's caching behavior and want to
+ * ensure a clean state after truncation. Implementations can check for the presence
+ * of Hibernate and evict the cache if applicable.
+ *
+ * @param applicationContext the application context
+ */
+ void cleanupCacheLayer(ApplicationContext applicationContext) {
+ // Clear the 2nd layer cache if it exists
+ if (ClassUtils.isPresent('org.hibernate.SessionFactory', this.getClass().classLoader)) {
+ def sessionFactory = applicationContext.getBean(
+ 'sessionFactory',
+ Class.forName('org.hibernate.SessionFactory')
+ )
+ def cache = InvokerHelper.getProperty(sessionFactory, 'cache')
+ if (cache) {
+ InvokerHelper.invokeMethod(cache, 'evictAllRegions', null)
+ }
+ }
+ }
}
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanup.groovy b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanup.groovy
index ee59e42d11..3163daac31 100644
--- a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanup.groovy
+++ b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanup.groovy
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.grails.testing.cleanup.core
import java.lang.annotation.ElementType
@@ -85,7 +84,7 @@ import java.lang.annotation.Target
/**
* The datasource entries to clean up. Each entry can be a plain datasource bean name
* (e.g., {@code "dataSource"}) or a datasource-to-type mapping
- * (e.g., {@code "dataSource:h2"}). If empty (the default), all datasources found
+ * (e.g., {@code "dataSource:h2"}). If empty (the default), all data sources found
* in the application context will be cleaned using auto-discovery.
*
* @return an array of datasource entries
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupContext.groovy b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupContext.groovy
index 13aa4933e6..10fdba73dd 100644
--- a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupContext.groovy
+++ b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupContext.groovy
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.grails.testing.cleanup.core
import javax.sql.DataSource
@@ -28,7 +27,7 @@ import org.springframework.context.ApplicationContext
/**
* Context that holds the discovered {@link DatabaseCleaner} implementations and
- * provides access to the application's datasources for cleanup operations.
+ * provides access to the application's data sources for cleanup operations.
*
* <p>Multiple cleaners can be registered (one per database type). When performing cleanup,
* the context matches each datasource to an appropriate cleaner using either an explicit
@@ -41,31 +40,39 @@ import org.springframework.context.ApplicationContext
class DatabaseCleanupContext {
private ApplicationContext applicationContext
- final Map<String, DatabaseCleaner> cleanersByType
+ private final Map<String, DatabaseCleaner> cleanersByType
DatabaseCleanupContext(List<DatabaseCleaner> cleaners) {
cleanersByType = createCleanersMap(cleaners)
}
private static Map<String, DatabaseCleaner> createCleanersMap(List<DatabaseCleaner> cleaners) {
- Map<String, DatabaseCleaner> typeMap = [:]
- for (DatabaseCleaner cleaner : cleaners) {
- def type = cleaner.databaseType()
- if (!type || type.trim().isEmpty()) {
+ def typeMap = [:] as Map<String, DatabaseCleaner>
+ cleaners.each {
+ def type = it.databaseType()?.trim()
+ if (!type) {
throw new IllegalStateException(
- "DatabaseCleaner implementation ${cleaner.class.name} returned a null or empty databaseType()" as String)
+ "DatabaseCleaner implementation $it.class.name " +
+ 'returned a null or empty databaseType()'
+ )
}
-
- DatabaseCleaner existing = typeMap.get(type)
+ def existing = typeMap[type]
if (existing) {
throw new IllegalStateException(
- "Duplicate databaseType '${type}' declared by both ${existing.class.name} and ${cleaner.class.name}. Each DatabaseCleaner must declare a unique databaseType." as String)
+ "Duplicate databaseType '$type' declared by both " +
+ "$existing.class.name and $it.class.name. " +
+ 'Each DatabaseCleaner must declare a unique databaseType.'
+ )
}
- typeMap.put(type, cleaner)
- log.debug('Discovered DatabaseCleaner implementation: {} (type: {})', cleaner.class.name, type)
+ typeMap[type] = it
+ log.debug(
+ 'Discovered DatabaseCleaner implementation: {} (type: {})',
+ it.class.name,
+ type
+ )
}
- Collections.unmodifiableMap(typeMap)
+ typeMap.asImmutable()
}
/**
@@ -84,14 +91,14 @@ class DatabaseCleanupContext {
}
/**
- * Performs cleanup on datasources found in the application context using the
+ * Performs cleanup on data sources found in the application context using the
* provided mapping from the {@link DatabaseCleanup} annotation.
*
- * <p>If the mapping specifies explicit database types for datasources, those types
+ * <p>If the mapping specifies explicit database types for data sources, those types
* are used to look up the cleaner directly. Otherwise, auto-discovery via
* {@link DatabaseCleaner#supports(DataSource)} is used.</p>
*
- * @param mapping the parsed annotation value describing which datasources to clean
+ * @param mapping the parsed annotation value describing which data sources to clean
* and optionally which cleaner types to use
* @return a list of {@link DatabaseCleanupStats}, one per datasource cleaned
* @throws IllegalStateException if a datasource marked for cleanup has no
@@ -101,63 +108,100 @@ class DatabaseCleanupContext {
*/
List<DatabaseCleanupStats> performCleanup(DatasourceCleanupMapping mapping) {
if (!applicationContext) {
- throw new IllegalStateException('Cannot perform database cleanup: ApplicationContext is not available')
+ throw new IllegalStateException(
+ 'Cannot perform database cleanup: ApplicationContext is not available'
+ )
}
if (!cleanersByType) {
- throw new IllegalStateException('Cannot perform database cleanup: no DatabaseCleaner implementations found')
+ throw new IllegalStateException(
+ 'Cannot perform database cleanup: no DatabaseCleaner implementations found'
+ )
}
- Map<String, DataSource> allDataSources = applicationContext.getBeansOfType(DataSource)
- List<DatabaseCleanupStats> allStats = []
+ def allDataSources = applicationContext.getBeansOfType(DataSource)
+ def allStats = [] as List<DatabaseCleanupStats>
if (mapping.cleanAll) {
- // Clean all datasources using auto-discovery
- allDataSources.each { String beanName, DataSource dataSource ->
- DatabaseCleaner cleaner = findCleanerFor(dataSource)
+ // Clean all data sources using auto-discovery
+ allDataSources.each { beanName, dataSource ->
+ def cleaner = findCleanerFor(dataSource)
if (!cleaner) {
throw new IllegalStateException(
- "No DatabaseCleaner implementation found that supports datasource '${beanName}'. Ensure that a database-specific cleanup library (e.g., grails-testing-support-cleanup-h2) is on the classpath for each database type used in your tests. Available cleaners: ${cleanersByType.values().collect { it.databaseType() }}" as String)
+ 'No DatabaseCleaner implementation found that supports ' +
+ "datasource '$beanName'. Ensure that a database-specific " +
+ 'cleanup library (e.g., grails-testing-support-cleanup-h2) ' +
+ 'is on the classpath for each database type used in your tests. ' +
+ "Available cleaners: ${cleanersByType.values()*.databaseType()}"
+ )
}
- log.debug('Cleaning up datasource: {} (using {} cleaner)', beanName, cleaner.databaseType())
- DatabaseCleanupStats stats = cleaner.cleanup(applicationContext, dataSource)
+ log.debug(
+ 'Cleaning up datasource: {} (using {} cleaner)',
+ beanName,
+ cleaner.databaseType()
+ )
+ def stats = cleaner.cleanup(applicationContext, dataSource)
stats.datasourceName = beanName
if (stats.tableRowCounts) {
- log.debug('Cleaned {} tables from datasource {}', stats.tableRowCounts.size(), beanName)
+ log.debug(
+ 'Cleaned {} tables from datasource {}',
+ stats.tableRowCounts.size(),
+ beanName
+ )
}
- allStats.add(stats)
+ allStats << stats
}
} else {
- // Clean specific datasources per the mapping entries
- for (DatasourceCleanupMapping.Entry entry : mapping.entries) {
- DataSource dataSource = allDataSources.get(entry.datasourceName)
+ // Clean specific data sources per the mapping entries
+ mapping.entries.each {
+ def dsName = it.datasourceName
+ def dataSource = allDataSources[dsName]
if (!dataSource) {
throw new IllegalStateException(
- "Datasource '${entry.datasourceName}' specified in @DatabaseCleanup was not found in the application context. Available datasources: ${allDataSources.keySet()}" as String)
+ "Datasource '$dsName' specified in @DatabaseCleanup " +
+ 'was not found in the application context. ' +
+ "Available datasources: ${allDataSources.keySet()}"
+ )
}
- DatabaseCleaner cleaner
- if (entry.hasExplicitType()) {
- cleaner = cleanersByType.get(entry.databaseType)
- if (!cleaner) {
- throw new IllegalStateException(
- "No DatabaseCleaner found for database type '${entry.databaseType}' specified in @DatabaseCleanup for datasource '${entry.datasourceName}'. Available cleaner types: ${cleanersByType.keySet()}" as String)
- }
- } else {
- cleaner = findCleanerFor(dataSource)
- if (!cleaner) {
+ def cleaner = it.hasExplicitType() ?
+ cleanersByType[it.databaseType] :
+ findCleanerFor(dataSource)
+
+ if (!cleaner) {
+ if (it.hasExplicitType()) {
throw new IllegalStateException(
- "No DatabaseCleaner implementation found that supports datasource '${entry.datasourceName}'. Ensure that a database-specific cleanup library (e.g., grails-testing-support-cleanup-h2) is on the classpath, or specify the database type explicitly: '${entry.datasourceName}:type'. Available cleaners: ${cleanersByType.values().collect { it.databaseType() }}" as String)
+ "No DatabaseCleaner found for database type '$it.databaseType' " +
+ "specified in @DatabaseCleanup for datasource '$dsName'. " +
+ "Available cleaner types: ${cleanersByType.keySet()}"
+ )
}
+ throw new IllegalStateException(
+ "No DatabaseCleaner implementation found that supports datasource '$dsName'. " +
+ 'Ensure that a database-specific cleanup library ' +
+ '(e.g., grails-testing-support-cleanup-h2) is on the classpath, ' +
+ "or specify the database type explicitly: '$dsName:type'. " +
+ "Available cleaners: ${cleanersByType.values()*.databaseType()}"
+ )
}
- log.debug('Cleaning up datasource: {} (using {} cleaner)', entry.datasourceName, cleaner.databaseType())
- DatabaseCleanupStats stats = cleaner.cleanup(applicationContext, dataSource)
- stats.datasourceName = entry.datasourceName
+ log.debug(
+ 'Cleaning up datasource: {} (using {} cleaner)',
+ dsName,
+ cleaner.databaseType()
+ )
+ def stats = cleaner.cleanup(applicationContext, dataSource)
+ stats.datasourceName = dsName
+
if (stats.tableRowCounts) {
- log.debug('Cleaned {} tables from datasource {}', stats.tableRowCounts.size(), entry.datasourceName)
+ log.debug(
+ 'Cleaned {} tables from datasource {}',
+ stats.tableRowCounts.size(),
+ dsName
+ )
}
- allStats.add(stats)
+
+ allStats << stats
}
}
@@ -171,11 +215,6 @@ class DatabaseCleanupContext {
* @return the matching cleaner, or {@code null} if none supports it
*/
private DatabaseCleaner findCleanerFor(DataSource dataSource) {
- for (DatabaseCleaner cleaner : cleanersByType.values()) {
- if (cleaner.supports(dataSource)) {
- return cleaner
- }
- }
- null
+ cleanersByType.values().find { it.supports(dataSource) }
}
}
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupExtension.groovy b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupExtension.groovy
index 375709dacb..b50524f8d9 100644
--- a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupExtension.groovy
+++ b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupExtension.groovy
@@ -16,20 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.grails.testing.cleanup.core
-import java.lang.reflect.Method
-
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
-import org.springframework.boot.test.context.SpringBootTest
-
import org.spockframework.runtime.extension.IGlobalExtension
-import org.spockframework.runtime.model.FeatureInfo
import org.spockframework.runtime.model.SpecInfo
+import org.springframework.boot.test.context.SpringBootTest
+
/**
* Spock global extension that detects the {@link DatabaseCleanup} annotation on test classes
* and methods, and registers the {@link DatabaseCleanupInterceptor} to perform database
@@ -74,8 +70,8 @@ class DatabaseCleanupExtension implements IGlobalExtension {
@Override
void start() {
- ServiceLoader<DatabaseCleaner> cleanerLoader = ServiceLoader.load(DatabaseCleaner)
- List<DatabaseCleaner> cleaners = cleanerLoader.toList()
+ def cleanerLoader = ServiceLoader.load(DatabaseCleaner)
+ def cleaners = cleanerLoader.toList()
if (cleaners.isEmpty()) {
log.debug('No DatabaseCleaner implementations found on classpath')
@@ -92,21 +88,28 @@ class DatabaseCleanupExtension implements IGlobalExtension {
}
// Without an application context, there can be no database
- boolean integrationEnvironment = spec.isAnnotationPresent(SpringBootTest) && spec.getAnnotation(SpringBootTest).webEnvironment() in [SpringBootTest.WebEnvironment.DEFINED_PORT, SpringBootTest.WebEnvironment.RANDOM_PORT]
+ boolean integrationEnvironment =
+ spec.isAnnotationPresent(SpringBootTest)
+ && spec.getAnnotation(SpringBootTest).webEnvironment() in [
+ SpringBootTest.WebEnvironment.DEFINED_PORT,
+ SpringBootTest.WebEnvironment.RANDOM_PORT
+ ]
if (!integrationEnvironment) {
if (hasDatabaseCleanupAnnotation(spec)) {
throw new IllegalStateException(
- "@DatabaseCleanup requires an environment with an ApplicationContext. Add @Integration or define the web environment on @SpringBootTest. Spec: ${spec.name}" as String)
+ '@DatabaseCleanup requires an environment with an ApplicationContext. ' +
+ 'Add @Integration or define the web environment on @SpringBootTest. ' +
+ "Spec: $spec.name")
}
return
}
boolean classAnnotated = spec.isAnnotationPresent(DatabaseCleanup)
if (classAnnotated) {
- DatabaseCleanup annotation = spec.getAnnotation(DatabaseCleanup)
- DatasourceCleanupMapping mapping = DatasourceCleanupMapping.parse(annotation.value())
- ApplicationContextResolver resolver = createResolver(annotation.resolver())
- DatabaseCleanupInterceptor interceptor = new DatabaseCleanupInterceptor(context, true, mapping, resolver)
+ def annotation = spec.getAnnotation(DatabaseCleanup)
+ def mapping = DatasourceCleanupMapping.parse(annotation.value())
+ def resolver = createResolver(annotation.resolver())
+ def interceptor = new DatabaseCleanupInterceptor(context, true, mapping, resolver)
spec.addSetupInterceptor(interceptor)
spec.addCleanupInterceptor(interceptor)
log.debug('Registered DatabaseCleanupInterceptor for spec: {} (class-level)', spec.name)
@@ -120,21 +123,17 @@ class DatabaseCleanupExtension implements IGlobalExtension {
}
// Check for method-level annotations on feature methods
- boolean hasMethodAnnotation = false
- for (FeatureInfo feature : spec.features) {
- if (feature.featureMethod.isAnnotationPresent(DatabaseCleanup)) {
- hasMethodAnnotation = true
- break
- }
+ boolean hasMethodAnnotation = spec.features.any {
+ it.featureMethod.isAnnotationPresent(DatabaseCleanup)
}
if (hasMethodAnnotation) {
// For method-level, pass a clean-all mapping as default; the interceptor reads
// each method's own annotation at runtime.
// Use the default resolver; the interceptor will read the method-level resolver at runtime.
- DatasourceCleanupMapping defaultMapping = DatasourceCleanupMapping.parse(new String[0])
- ApplicationContextResolver defaultResolver = new DefaultApplicationContextResolver()
- DatabaseCleanupInterceptor interceptor = new DatabaseCleanupInterceptor(context, false, defaultMapping, defaultResolver)
+ def defaultMapping = DatasourceCleanupMapping.parse(new String[0])
+ def defaultResolver = new DefaultApplicationContextResolver()
+ def interceptor = new DatabaseCleanupInterceptor(context, false, defaultMapping, defaultResolver)
spec.addSetupInterceptor(interceptor)
spec.addCleanupInterceptor(interceptor)
log.debug('Registered DatabaseCleanupInterceptor for spec: {} (method-level)', spec.name)
@@ -153,7 +152,10 @@ class DatabaseCleanupExtension implements IGlobalExtension {
}
catch (Exception e) {
throw new IllegalStateException(
- "Failed to instantiate ApplicationContextResolver: ${resolverClass.name}. Ensure it has a no-arg constructor." as String, e)
+ 'Failed to instantiate ApplicationContextResolver: ' +
+ "$resolverClass.name. Ensure it has a no-arg constructor.",
+ e
+ )
}
}
@@ -171,19 +173,22 @@ class DatabaseCleanupExtension implements IGlobalExtension {
*/
private static void validateNoAnnotationOnNonFeatureMethods(SpecInfo spec) {
// Collect all feature method names for comparison
- Set<String> featureMethodNames = [] as Set
- for (FeatureInfo feature : spec.features) {
- featureMethodNames.add(feature.featureMethod.name)
- }
+ def featureMethodNames = spec.features*.name as Set<String>
// Check all declared methods in the spec class for misplaced annotations
// This necessarily uses spec.reflection since we need to scan raw Java methods
// that are not exposed as Spock features
- for (Method method : spec.reflection.declaredMethods) {
- if (method.isAnnotationPresent(DatabaseCleanup) && !featureMethodNames.contains(method.name)) {
- throw new IllegalStateException(
- "@DatabaseCleanup annotation on method '${method.name}' in ${spec.reflection.name} is not valid. @DatabaseCleanup can only be applied to Spock feature methods (test methods) or at the class level. It cannot be applied to setup(), cleanup(), setupSpec(), or cleanupSpec() methods." as String)
- }
+ def invalid = spec.reflection.declaredMethods.find {
+ it.isAnnotationPresent(DatabaseCleanup) && !featureMethodNames.contains(it.name)
+ }
+ if (invalid) {
+ throw new IllegalStateException(
+ "@DatabaseCleanup annotation on method '$invalid.name' " +
+ "in $spec.reflection.name is not valid. @DatabaseCleanup " +
+ 'can only be applied to Spock feature methods (test methods) ' +
+ 'or at the class level. It cannot be applied to setup(), ' +
+ 'cleanup(), setupSpec(), or cleanupSpec() methods.'
+ )
}
}
@@ -192,14 +197,7 @@ class DatabaseCleanupExtension implements IGlobalExtension {
* class level or on any feature method.
*/
private static boolean hasDatabaseCleanupAnnotation(SpecInfo spec) {
- if (spec.isAnnotationPresent(DatabaseCleanup)) {
- return true
- }
- for (FeatureInfo feature : spec.features) {
- if (feature.featureMethod.isAnnotationPresent(DatabaseCleanup)) {
- return true
- }
- }
- false
+ spec.isAnnotationPresent(DatabaseCleanup) ||
+ spec.features.any { it.featureMethod.isAnnotationPresent(DatabaseCleanup) }
}
}
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupInterceptor.groovy b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupInterceptor.groovy
index e726b60fc7..d1e5921665 100644
--- a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupInterceptor.groovy
+++ b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupInterceptor.groovy
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.grails.testing.cleanup.core
import groovy.transform.CompileStatic
@@ -27,8 +26,6 @@ import org.spockframework.runtime.extension.IMethodInvocation
import org.springframework.context.ApplicationContext
-import java.text.SimpleDateFormat
-
/**
* Spock method interceptor that performs database cleanup after tests annotated
* with {@link DatabaseCleanup}. Supports both class-level and method-level annotations.
@@ -38,8 +35,8 @@ import java.text.SimpleDateFormat
* {@link DatabaseCleanupContext}. After cleanup completes, the ThreadLocal is cleared.</p>
*
* <p>When datasource entries are specified in the annotation (with optional database type
- * mappings), only those datasources are cleaned using the specified or auto-discovered
- * cleaners. Otherwise, all datasources are cleaned.</p>
+ * mappings), only those data sources are cleaned using the specified or auto-discovered
+ * cleaners. Otherwise, all datas ources are cleaned.</p>
*/
@Slf4j
@CompileStatic
@@ -58,8 +55,12 @@ class DatabaseCleanupInterceptor extends AbstractMethodInterceptor {
* for method-level cleanup, the method's own annotation values are parsed at runtime
* @param resolver the strategy for resolving the ApplicationContext from test instances
*/
- DatabaseCleanupInterceptor(DatabaseCleanupContext context, boolean classLevelCleanup,
- DatasourceCleanupMapping mapping, ApplicationContextResolver resolver) {
+ DatabaseCleanupInterceptor(
+ DatabaseCleanupContext context,
+ boolean classLevelCleanup,
+ DatasourceCleanupMapping mapping,
+ ApplicationContextResolver resolver
+ ) {
this.context = context
this.classLevelCleanup = classLevelCleanup
this.mapping = mapping
@@ -83,15 +84,22 @@ class DatabaseCleanupInterceptor extends AbstractMethodInterceptor {
}
finally {
try {
- def methodMapping = invocation.feature?.featureMethod?.isAnnotationPresent(DatabaseCleanup)
+ def methodMapping = invocation.
+ feature?.
+ featureMethod?.
+ isAnnotationPresent(DatabaseCleanup)
if (!classLevelCleanup && !methodMapping) {
return
}
-
- log.debug('Performing database cleanup after test method: {}', invocation.feature?.name ?: 'unknown')
- DatasourceCleanupMapping selectedMapping = methodMapping ? getMethodMapping(invocation) : mapping
+ log.debug(
+ 'Performing database cleanup after test method: {}',
+ invocation.feature?.name ?: 'unknown'
+ )
+ def selectedMapping = methodMapping ?
+ getMethodMapping(invocation)
+ : mapping
long startTime = System.currentTimeMillis()
- List<DatabaseCleanupStats> stats = context.performCleanup(selectedMapping)
+ def stats = context.performCleanup(selectedMapping)
logStats(stats, startTime)
}
finally {
@@ -104,8 +112,13 @@ class DatabaseCleanupInterceptor extends AbstractMethodInterceptor {
* Gets the parsed mapping from the method-level @DatabaseCleanup annotation.
*/
private static DatasourceCleanupMapping getMethodMapping(IMethodInvocation invocation) {
- DatabaseCleanup annotation = invocation.feature?.featureMethod?.getAnnotation(DatabaseCleanup)
- annotation ? DatasourceCleanupMapping.parse(annotation.value()) : DatasourceCleanupMapping.parse(new String[0])
+ def annotation = invocation.
+ feature?.
+ featureMethod?.
+ getAnnotation(DatabaseCleanup)
+ annotation ?
+ DatasourceCleanupMapping.parse(annotation.value()) :
+ DatasourceCleanupMapping.parse(new String[0])
}
/**
@@ -119,20 +132,22 @@ class DatabaseCleanupInterceptor extends AbstractMethodInterceptor {
return
}
- ApplicationContext appCtx = resolver.resolve(invocation)
+ def appCtx = resolver.resolve(invocation)
if (appCtx) {
context.applicationContext = appCtx
}
else {
throw new IllegalStateException(
- 'Could not resolve ApplicationContext from test instance. Ensure the spec is annotated with @Integration.')
+ 'Could not resolve ApplicationContext from test instance. ' +
+ 'Ensure the spec is annotated with @Integration.'
+ )
}
}
/**
* Logs cleanup statistics and overall timing information for the cleanup operation.
*
- * @param statsList the list of cleanup statistics from individual datasources
+ * @param statsList the list of cleanup statistics from individual data sources
* @param overallStartTime the overall start time of the cleanup operation
*/
private static void logStats(List<DatabaseCleanupStats> statsList, long overallStartTime) {
@@ -140,20 +155,20 @@ class DatabaseCleanupInterceptor extends AbstractMethodInterceptor {
long overallEndTime = System.currentTimeMillis()
long overallDuration = overallEndTime - overallStartTime
- String separator = '=========================================================='
- String startTimeFormatted = DatabaseCleanupStats.formatTime(overallStartTime)
- String endTimeFormatted = DatabaseCleanupStats.formatTime(overallEndTime)
+ def separator = '=========================================================='
+ def startTimeFormatted = DatabaseCleanupStats.formatTime(overallStartTime)
+ def endTimeFormatted = DatabaseCleanupStats.formatTime(overallEndTime)
- System.out.println(separator)
- System.out.println('Overall Cleanup Timing')
- System.out.println("Start Time: ${startTimeFormatted}")
- System.out.println("End Time: ${endTimeFormatted}")
- System.out.println("Duration: ${overallDuration} ms")
- System.out.println(separator)
+ println(separator)
+ println('Overall Cleanup Timing')
+ println("Start Time: $startTimeFormatted")
+ println("End Time: $endTimeFormatted")
+ println("Duration: $overallDuration ms")
+ println(separator)
- for (DatabaseCleanupStats stats : statsList) {
- if (stats.tableRowCounts) {
- System.out.println(stats.toFormattedReport())
+ statsList.each {
+ if (it.tableRowCounts) {
+ println(it.toFormattedReport())
}
}
}
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupStats.groovy b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupStats.groovy
index 68c2eed9d3..c7d3e2d0bc 100644
--- a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupStats.groovy
+++ b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupStats.groovy
@@ -16,12 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.grails.testing.cleanup.core
-import groovy.transform.CompileStatic
import java.text.SimpleDateFormat
+import groovy.transform.CompileStatic
+
/**
* Captures statistics from a single datasource cleanup operation, including which
* tables were truncated and how many rows were in each table before truncation.
@@ -147,10 +147,10 @@ class DatabaseCleanupStats {
String separator = '=========================================================='
String divider = '----------------------------------------------------------'
- StringBuilder sb = new StringBuilder()
+ def sb = new StringBuilder()
sb.append(separator).append('\n')
if (datasourceName) {
- sb.append("Database Cleanup Stats (datasource: ${datasourceName})").append('\n')
+ sb.append("Database Cleanup Stats (datasource: $datasourceName)").append('\n')
}
else {
sb.append('Database Cleanup Stats').append('\n')
@@ -165,7 +165,7 @@ class DatabaseCleanupStats {
sb.append("End Time: ${formatTime(endTimeMillis)}").append('\n')
}
if (startTimeMillis > 0L && endTimeMillis > 0L) {
- sb.append("Duration: ${durationMillis} ms").append('\n')
+ sb.append("Duration: $durationMillis ms").append('\n')
}
}
@@ -193,8 +193,8 @@ class DatabaseCleanupStats {
* @return the formatted time string
*/
static String formatTime(long timeMillis) {
- SimpleDateFormat sdf = new SimpleDateFormat('yyyy-MM-dd\'T\'HH:mm:ss.SSS\'Z\'')
- sdf.setTimeZone(TimeZone.getTimeZone('UTC'))
- sdf.format(new Date(timeMillis))
+ new SimpleDateFormat(/yyyy-MM-dd'T'HH:mm:ss.SSS'Z'/).tap {
+ timeZone = TimeZone.getTimeZone('UTC')
+ }.format(new Date(timeMillis))
}
}
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatasourceCleanupMapping.groovy b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatasourceCleanupMapping.groovy
index b628bfb82a..e1f724edbb 100644
--- a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatasourceCleanupMapping.groovy
+++ b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatasourceCleanupMapping.groovy
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.grails.testing.cleanup.core
import groovy.transform.CompileStatic
@@ -33,18 +32,18 @@ import groovy.transform.CompileStatic
* cleaner that declares the specified {@link DatabaseCleaner#databaseType()}</li>
* </ul>
*
- * <p>If the annotation value is empty (the default), all datasources in the application
+ * <p>If the annotation value is empty (the default), all data sources in the application
* context are cleaned using auto-discovery.</p>
*
* <p>Examples:</p>
* <pre>
- * // Clean all datasources (auto-discover cleaners)
+ * // Clean all data sources (auto-discover cleaners)
* @DatabaseCleanup
*
- * // Clean specific datasources (auto-discover cleaners)
+ * // Clean specific data sources (auto-discover cleaners)
* @DatabaseCleanup(['dataSource', 'dataSource_secondary'])
*
- * // Clean specific datasources with explicit cleaner types
+ * // Clean specific data sources with explicit cleaner types
* @DatabaseCleanup(['dataSource:h2', 'dataSource_pg:postgresql'])
*
* // Mixed: some explicit, some auto-discovered
@@ -71,12 +70,14 @@ class DatasourceCleanupMapping {
* @return {@code true} if this entry has an explicit database type mapping
*/
boolean hasExplicitType() {
- databaseType as boolean
+ databaseType
}
@Override
String toString() {
- hasExplicitType() ? "${datasourceName}:${databaseType}" : datasourceName
+ hasExplicitType() ?
+ "$datasourceName:$databaseType" :
+ datasourceName
}
}
@@ -84,7 +85,7 @@ class DatasourceCleanupMapping {
private final boolean cleanAll
private DatasourceCleanupMapping(List<Entry> entries, boolean cleanAll) {
- this.entries = Collections.unmodifiableList(new ArrayList<>(entries))
+ this.entries = entries.asImmutable()
this.cleanAll = cleanAll
}
@@ -96,8 +97,8 @@ class DatasourceCleanupMapping {
}
/**
- * @return {@code true} if no specific datasources were specified, meaning all
- * datasources in the application context should be cleaned
+ * @return {@code true} if no specific data sources were specified, meaning all
+ * datas ources in the application context should be cleaned
*/
boolean isCleanAll() {
cleanAll
@@ -114,37 +115,40 @@ class DatasourceCleanupMapping {
* @throws IllegalArgumentException if an entry has an empty datasource name or database type
*/
static DatasourceCleanupMapping parse(String[] annotationValues) {
- if (!annotationValues || annotationValues.length == 0) {
+ if (!annotationValues) {
return new DatasourceCleanupMapping([], true)
}
- List<Entry> entries = []
- for (String value : annotationValues) {
- if (!value || value.trim().isEmpty()) {
+ def entries = annotationValues.collect {
+ def v = it?.trim()
+ if (!v) {
throw new IllegalArgumentException(
- '@DatabaseCleanup contains a null or empty entry')
+ '@DatabaseCleanup contains a null or empty entry'
+ )
}
- int colonIdx = value.indexOf(':')
- if (colonIdx < 0) {
+ def parts = v.split(':', 2)*.trim()
+ if (parts.size() == 1) {
// No colon — datasource name only, auto-discover cleaner
- entries.add(new Entry(value.trim(), null))
+ return new Entry(parts[0], null)
+ }
+
+ def name = parts[0]
+ def type = parts[1]
+ if (!name) {
+ throw new IllegalArgumentException(
+ "Invalid @DatabaseCleanup entry '$it': " +
+ 'datasource name cannot be empty'
+ )
}
- else {
- String name = value.substring(0, colonIdx).trim()
- String type = value.substring(colonIdx + 1).trim()
-
- if (name.isEmpty()) {
- throw new IllegalArgumentException(
- "Invalid @DatabaseCleanup entry '${value}': datasource name cannot be empty")
- }
- if (type.isEmpty()) {
- throw new IllegalArgumentException(
- "Invalid @DatabaseCleanup entry '${value}': database type cannot be empty after ':'")
- }
-
- entries.add(new Entry(name, type))
+ if (!type) {
+ throw new IllegalArgumentException(
+ "Invalid @DatabaseCleanup entry '$it': " +
+ "database type cannot be empty after ':'"
+ )
}
+
+ new Entry(name, type)
}
new DatasourceCleanupMapping(entries, false)
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DefaultApplicationContextResolver.groovy b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DefaultApplicationContextResolver.groovy
index 617b38afda..ba0368f132 100644
--- a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DefaultApplicationContextResolver.groovy
+++ b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DefaultApplicationContextResolver.groovy
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.grails.testing.cleanup.core
import groovy.transform.CompileStatic
@@ -49,9 +48,9 @@ class DefaultApplicationContextResolver implements ApplicationContextResolver {
@Override
ApplicationContext resolve(IMethodInvocation invocation) {
- TestContext testContext = TestContextHolderListener.CURRENT.get()
+ def testContext = TestContextHolderListener.CURRENT.get()
if (testContext) {
- ApplicationContext ctx = testContext.applicationContext
+ def ctx = testContext.applicationContext
if (ctx) {
log.debug('Resolved ApplicationContext via TestContextHolderListener')
return ctx
@@ -59,6 +58,10 @@ class DefaultApplicationContextResolver implements ApplicationContextResolver {
}
throw new IllegalStateException(
- 'Could not resolve ApplicationContext. Ensure the spec is annotated with @Integration and that TestContextHolderListener is registered as a TestExecutionListener.')
+ 'Could not resolve ApplicationContext. ' +
+ 'Ensure the spec is annotated with @Integration ' +
+ 'and that TestContextHolderListener is registered ' +
+ 'as a TestExecutionListener.'
+ )
}
}
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/TestContextHolderListener.groovy b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/TestContextHolderListener.groovy
index 73304209ca..5241dec615 100644
--- a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/TestContextHolderListener.groovy
+++ b/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/TestContextHolderListener.groovy
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.grails.testing.cleanup.core
import groovy.transform.CompileStatic
diff --git a/grails-testing-support-cleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleaner.groovy b/grails-testing-support-cleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleaner.groovy
index b1a71a0f1a..c3cce96176 100644
--- a/grails-testing-support-cleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleaner.groovy
+++ b/grails-testing-support-cleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleaner.groovy
@@ -16,22 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.grails.testing.cleanup.h2
-import java.sql.Connection
-import java.sql.DatabaseMetaData
-
import javax.sql.DataSource
-import groovy.sql.GroovyResultSet
import groovy.sql.Sql
-import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.springframework.context.ApplicationContext
-import org.springframework.util.ClassUtils
import org.apache.grails.testing.cleanup.core.DatabaseCleaner
import org.apache.grails.testing.cleanup.core.DatabaseCleanupStats
@@ -49,6 +42,11 @@ import org.apache.grails.testing.cleanup.core.DatabaseCleanupStats
class H2DatabaseCleaner implements DatabaseCleaner {
private static final String DATABASE_TYPE = 'h2'
+ private static final String QUERY = '''
+ SELECT table_name, row_count_estimate
+ FROM information_schema.tables
+ WHERE table_schema = ? AND row_count_estimate > 0
+ '''
@Override
String databaseType() {
@@ -57,53 +55,36 @@ class H2DatabaseCleaner implements DatabaseCleaner {
@Override
boolean supports(DataSource dataSource) {
- Connection connection = null
- try {
- connection = dataSource.getConnection()
- DatabaseMetaData metaData = connection.getMetaData()
- String url = metaData.getURL()
- return url && url.startsWith('jdbc:h2:')
- }
- catch (Exception e) {
+ try (def con = dataSource.connection) {
+ return con.metaData?.URL?.startsWith('jdbc:h2:')
+ } catch (Exception e) {
log.debug('Could not determine if datasource is H2', e)
return false
}
- finally {
- if (connection) {
- try {
- connection.close()
- }
- catch (Exception ignored) {
- // ignore
- }
- }
- }
}
- @SuppressWarnings('SqlNoDataSourceInspection')
@Override
+ @SuppressWarnings('SqlNoDataSourceInspection')
DatabaseCleanupStats cleanup(ApplicationContext applicationContext, DataSource dataSource) {
- DatabaseCleanupStats stats = new DatabaseCleanupStats()
+ def stats = new DatabaseCleanupStats()
stats.start()
- String schemaName = H2DatabaseCleanupHelper.resolveSchemaName(dataSource)
+ def schemaName = H2DatabaseCleanupHelper.resolveSchemaName(dataSource)
if (!schemaName) {
log.warn('Could not resolve schema name for datasource, skipping cleanup')
stats.stop()
return stats
}
- Sql sql = new Sql(dataSource)
+ def sql = new Sql(dataSource)
try {
sql.execute('SET REFERENTIAL_INTEGRITY FALSE')
- String query = "SELECT table_name, row_count_estimate FROM information_schema.tables WHERE table_schema = '${schemaName}' AND row_count_estimate > 0" as String
- sql.eachRow(query) { GroovyResultSet row ->
- String tableName = row['table_name'] as String
- stats.addTableRowCount(tableName, row['row_count_estimate'] as Long)
+ sql.eachRow(QUERY, [schemaName] as List<Object>) { row ->
+ def tableName = row.getString('table_name')
+ stats.addTableRowCount(tableName, row.getLong('row_count_estimate'))
log.debug('Truncating table: {}', tableName)
- sql.executeUpdate("TRUNCATE TABLE \"${tableName}\"" as String)
+ sql.executeUpdate(/TRUNCATE TABLE "$tableName"/)
}
-
cleanupCacheLayer(applicationContext)
}
finally {
@@ -119,13 +100,4 @@ class H2DatabaseCleaner implements DatabaseCleaner {
stats
}
-
- @CompileDynamic
- private void cleanupCacheLayer(ApplicationContext applicationContext) {
- // Clear the 2nd layer cache if it exists
- if (ClassUtils.isPresent('org.hibernate.SessionFactory', this.class.classLoader)) {
- def sessionFactory = applicationContext.getBean('sessionFactory', Class.forName('org.hibernate.SessionFactory'))
- sessionFactory?.cache?.evictAllRegions()
- }
- }
}
diff --git a/grails-testing-support-cleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanupHelper.groovy b/grails-testing-support-cleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanupHelper.groovy
index 6811b0df06..8b8480c19f 100644
--- a/grails-testing-support-cleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanupHelper.groovy
+++ b/grails-testing-support-cleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanupHelper.groovy
@@ -16,12 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.grails.testing.cleanup.h2
-import java.sql.Connection
-import java.sql.DatabaseMetaData
-
import javax.sql.DataSource
import groovy.transform.CompileStatic
@@ -45,37 +41,21 @@ class H2DatabaseCleanupHelper {
* @return the schema name, or {@code null} if it cannot be determined
*/
static String resolveSchemaName(DataSource dataSource) {
- Connection connection = null
- try {
- connection = dataSource.getConnection()
- String schema = connection.getSchema()
+ try (def con = dataSource.getConnection()) {
+ def schema = con.getSchema()
if (schema) {
log.debug('Resolved schema name from connection: {}', schema)
return schema
}
-
- // Fallback: try to get the schema from the database metadata URL
- DatabaseMetaData metaData = connection.getMetaData()
- String url = metaData.getURL()
+ def url = con.metaData.URL
if (url) {
- schema = extractSchemaFromUrl(url)
- log.debug('Resolved schema name from URL {}: {}', url, schema)
- return schema
+ def extracted = extractSchemaFromUrl(url)
+ log.debug('Resolved schema name from URL {}: {}', url, extracted)
+ return extracted
}
- }
- catch (Exception e) {
+ } catch (Exception e) {
log.warn('Failed to resolve schema name from datasource', e)
}
- finally {
- if (connection) {
- try {
- connection.close()
- }
- catch (Exception ignored) {
- // ignore
- }
- }
- }
null
}
@@ -94,53 +74,48 @@ class H2DatabaseCleanupHelper {
* @return the uppercase schema name, or {@code null} if the URL format is not recognized
*/
static String extractSchemaFromUrl(String url) {
- if (!url) {
+ if (!url?.startsWith('jdbc:h2:')) {
return null
}
// Handle H2 in-memory URLs: jdbc:h2:mem:dbName or jdbc:h2:mem:dbName;params
if (url.startsWith('jdbc:h2:mem:')) {
- String remainder = url.substring('jdbc:h2:mem:'.length())
- // Remove any trailing parameters after ';'
- int semicolonIdx = remainder.indexOf(';')
- if (semicolonIdx >= 0) {
- remainder = remainder.substring(0, semicolonIdx)
- }
- return remainder ? remainder.toUpperCase() : null
+ def name = stripParams(url.substring('jdbc:h2:mem:'.length()))
+ return toSchema(name)
}
- // Handle H2 file-based URLs: jdbc:h2:./dbName, jdbc:h2:file:./path/dbName, jdbc:h2:tcp://host/dbName
- if (url.startsWith('jdbc:h2:')) {
- String remainder = url.substring('jdbc:h2:'.length())
-
- // Remove protocol prefixes (tcp://, ssl://)
- if (remainder.startsWith('tcp://') || remainder.startsWith('ssl://')) {
- int slashIdx = remainder.indexOf('/', remainder.indexOf('//') + 2)
- if (slashIdx >= 0) {
- remainder = remainder.substring(slashIdx + 1)
- }
- }
+ def remainder = url.substring('jdbc:h2:'.length())
- // Remove 'file:' prefix
- if (remainder.startsWith('file:')) {
- remainder = remainder.substring('file:'.length())
+ // Remove protocol prefixes (tcp://, ssl://)
+ if (remainder.startsWith('tcp://') || remainder.startsWith('ssl://')) {
+ int slashIdx = remainder.indexOf('/', remainder.indexOf('//') + 2)
+ if (slashIdx >= 0) {
+ remainder = remainder.substring(slashIdx + 1)
}
+ }
- // Remove any trailing parameters after ';'
- int semicolonIdx = remainder.indexOf(';')
- if (semicolonIdx >= 0) {
- remainder = remainder.substring(0, semicolonIdx)
- }
+ // Remove 'file:' prefix
+ if (remainder.startsWith('file:')) {
+ remainder = remainder.substring('file:'.length())
+ }
- // Get the last path segment as the database name
- int lastSlash = remainder.lastIndexOf('/')
- if (lastSlash >= 0) {
- remainder = remainder.substring(lastSlash + 1)
- }
+ remainder = stripParams(remainder)
- return remainder ? remainder.toUpperCase() : null
+ // last path segment
+ int lastSlash = remainder.lastIndexOf('/')
+ if (lastSlash >= 0) {
+ remainder = remainder.substring(lastSlash + 1)
}
- null
+ return toSchema(remainder)
+ }
+
+ private static String stripParams(String s) {
+ int idx = s.indexOf(';')
+ idx >= 0 ? s.substring(0, idx) : s
+ }
+
+ private static String toSchema(String s) {
+ s ? s.toUpperCase() : null
}
}
diff --git a/grails-testing-support-cleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleaner.groovy b/grails-testing-support-cleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleaner.groovy
index 5ed1756602..089bdafbaa 100644
--- a/grails-testing-support-cleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleaner.groovy
+++ b/grails-testing-support-cleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleaner.groovy
@@ -16,22 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.grails.testing.cleanup.postgresql
-import java.sql.Connection
-import java.sql.DatabaseMetaData
-
import javax.sql.DataSource
-import groovy.sql.GroovyResultSet
import groovy.sql.Sql
-import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.springframework.context.ApplicationContext
-import org.springframework.util.ClassUtils
import org.apache.grails.testing.cleanup.core.DatabaseCleaner
import org.apache.grails.testing.cleanup.core.DatabaseCleanupStats
@@ -57,6 +50,16 @@ import org.apache.grails.testing.cleanup.core.DatabaseCleanupStats
class PostgresDatabaseCleaner implements DatabaseCleaner {
private static final String DATABASE_TYPE = 'postgresql'
+ private static final String QUERY = '''
+ SELECT n.nspname AS schemaname,
+ c.relname AS table_name,
+ c.reltuples::bigint AS row_count_estimate
+ FROM pg_class c
+ JOIN pg_namespace n ON n.oid = c.relnamespace
+ WHERE c.relkind = 'r'
+ AND n.nspname = ?
+ ORDER BY row_count_estimate DESC;
+ '''
@Override
String databaseType() {
@@ -65,45 +68,27 @@ class PostgresDatabaseCleaner implements DatabaseCleaner {
@Override
boolean supports(DataSource dataSource) {
- Connection connection = null
- try {
- connection = dataSource.getConnection()
- DatabaseMetaData metaData = connection.getMetaData()
- String url = metaData.getURL()
- return url && url.startsWith('jdbc:postgresql:')
- }
- catch (Exception e) {
+ try (def con = dataSource.connection) {
+ return con.metaData?.URL?.startsWith('jdbc:postgresql:')
+ } catch (Exception e) {
log.debug('Could not determine if datasource is PostgreSQL', e)
return false
}
- finally {
- if (connection) {
- try {
- connection.close()
- }
- catch (Exception ignored) {
- // ignore
- }
- }
- }
}
- @SuppressWarnings('SqlNoDataSourceInspection')
@Override
+ @SuppressWarnings('SqlNoDataSourceInspection')
DatabaseCleanupStats cleanup(ApplicationContext applicationContext, DataSource dataSource) {
- DatabaseCleanupStats stats = new DatabaseCleanupStats()
- stats.start()
- Sql sql = new Sql(dataSource)
+ def stats = new DatabaseCleanupStats().tap { start() }
+ def sql = new Sql(dataSource)
try {
// Disable all triggers and referential integrity checks for this session
// This is more efficient than using CASCADE on each truncate
sql.execute('SET session_replication_role = replica')
-
- String currentSchema = PostgresDatabaseCleanupHelper.resolveCurrentSchema(dataSource)
+ def currentSchema = PostgresDatabaseCleanupHelper.resolveCurrentSchema(dataSource)
log.debug('Cleaning schema: {}', currentSchema)
cleanupSchema(sql, currentSchema, stats)
-
cleanupCacheLayer(applicationContext)
}
finally {
@@ -117,32 +102,19 @@ class PostgresDatabaseCleaner implements DatabaseCleaner {
}
stats.stop()
}
-
stats
}
@SuppressWarnings('SqlNoDataSourceInspection')
- private void cleanupSchema(Sql sql, String schemaName, DatabaseCleanupStats stats) {
- String query = """
- SELECT n.nspname AS schemaname,
- c.relname AS table_name,
- c.reltuples::bigint AS row_count_estimate
- FROM pg_class c
- JOIN pg_namespace n ON n.oid = c.relnamespace
- WHERE c.relkind = 'r'
- AND n.nspname = '${schemaName}'
- ORDER BY row_count_estimate DESC;
- """ as String
-
- List<String> tablesInSchema = []
- sql.eachRow(query) { GroovyResultSet row ->
- String tableName = row['table_name'] as String
+ private static void cleanupSchema(Sql sql, String schemaName, DatabaseCleanupStats stats) {
+ def tablesInSchema = [] as List<String>
+ sql.eachRow(QUERY, [schemaName] as List<Object>) { row ->
+ def tableName = row.getString('table_name')
tablesInSchema << tableName
-
- def rowCount = row['row_count_estimate'] as Long
+ def rowCount = row.getLong('row_count_estimate')
if (stats.detailedStatCollection) {
if (rowCount == -1) {
- String countQuery = "SELECT COUNT(*) AS cnt FROM ${tableName}" as String
+ def countQuery = "SELECT COUNT(*) AS cnt FROM $tableName" as String
rowCount = sql.firstRow(countQuery)?.cnt as Long ?: 0L
}
}
@@ -150,17 +122,11 @@ class PostgresDatabaseCleaner implements DatabaseCleaner {
}
if (tablesInSchema) {
- log.debug('Truncating tables: {}', tablesInSchema.join(','))
- sql.executeUpdate("TRUNCATE TABLE ${tablesInSchema.collect { "\"$it\"" }.join(',')} RESTART IDENTITY CASCADE" as String)
- }
- }
-
- @CompileDynamic
- private void cleanupCacheLayer(ApplicationContext applicationContext) {
- // Clear the 2nd layer cache if it exists
- if (ClassUtils.isPresent('org.hibernate.SessionFactory', this.class.classLoader)) {
- def sessionFactory = applicationContext.getBean('sessionFactory', Class.forName('org.hibernate.SessionFactory'))
- sessionFactory?.cache?.evictAllRegions()
+ log.debug('Truncating tables: {}', tablesInSchema.join(', '))
+ def tables = tablesInSchema.collect { "\"$it\"" }.join(',')
+ sql.executeUpdate(
+ "TRUNCATE TABLE $tables RESTART IDENTITY CASCADE" as String
+ )
}
}
}
diff --git a/grails-testing-support-cleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanupHelper.groovy b/grails-testing-support-cleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanupHelper.groovy
index a79e65d60a..a6816b13db 100644
--- a/grails-testing-support-cleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanupHelper.groovy
+++ b/grails-testing-support-cleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanupHelper.groovy
@@ -16,67 +16,52 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.grails.testing.cleanup.postgresql
-import java.sql.Connection
-import java.sql.DatabaseMetaData
-
import javax.sql.DataSource
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
/**
- * Helper utility for PostgreSQL database cleanup operations. Provides PostgreSQL-specific logic such as
- * resolving the current schema from a {@link DataSource} by inspecting JDBC connection metadata
- * and parsing PostgreSQL JDBC URLs.
+ * Helper utility for PostgreSQL database cleanup operations.
+ * Provides PostgreSQL-specific logic such as resolving the
+ * current schema from a {@link DataSource} by inspecting
+ * JDBC connection metadata and parsing PostgreSQL JDBC URLs.
*/
@Slf4j
@CompileStatic
class PostgresDatabaseCleanupHelper {
/**
- * Resolves the current schema for the given PostgreSQL datasource by inspecting the JDBC connection metadata.
- * If the JDBC URL contains a `currentSchema` parameter, returns that schema.
+ * Resolves the current schema for the given PostgreSQL datasource
+ * by inspecting the JDBC connection metadata. If the JDBC URL
+ * contains a `currentSchema` parameter, returns that schema.
* Otherwise, returns the connection's current schema.
*
* @param dataSource the datasource to resolve the schema for
* @return the schema name, or {@code null} if it cannot be determined
*/
static String resolveCurrentSchema(DataSource dataSource) {
- Connection connection = null
- try {
- connection = dataSource.getConnection()
- String schema = connection.getSchema()
+ try (def con = dataSource.connection) {
+ def schema = con.getSchema()
if (schema) {
log.debug('Resolved current schema from connection: {}', schema)
return schema
}
- // Fallback: try to get the schema from the database metadata URL
- DatabaseMetaData metaData = connection.getMetaData()
- String url = metaData.getURL()
+ def url = con.metaData.URL
if (url) {
schema = extractCurrentSchemaFromUrl(url)
- if (schema) {
- log.debug('Resolved current schema from URL {}: {}', url, schema)
- return schema
- }
- }
- }
- finally {
- if (connection) {
- try {
- connection.close()
- }
- catch (Exception ignored) {
- // ignore
- }
+ log.debug('Resolved current schema from URL {}: {}', url, schema)
+ return schema
}
}
-
- throw new IllegalStateException("Because postgres defaults to the search_path when currentSchema isn't defined, a schema should always be found")
+ throw new IllegalStateException(
+ 'Because postgres defaults to the search_path ' +
+ 'when currentSchema isn\'t defined, a schema ' +
+ 'should always be found'
+ )
}
/**
@@ -98,29 +83,18 @@ class PostgresDatabaseCleanupHelper {
return null
}
- // Look for currentSchema parameter in query string
- int questionIdx = url.indexOf('?')
- if (questionIdx < 0) {
+ int q = url.indexOf('?')
+ if (q < 0) {
return null
}
- String queryString = url.substring(questionIdx + 1)
- String[] params = queryString.split('&')
- for (String param : params) {
+ def query = url.substring(q + 1)
+ for (def param : query.split('&')) {
if (param.startsWith('currentSchema=')) {
- String schema = param.substring('currentSchema='.length())
- // URL decode if needed (handle common cases)
- if (schema) {
- // Remove any trailing parameters if present
- int ampIdx = schema.indexOf('&')
- if (ampIdx >= 0) {
- schema = schema.substring(0, ampIdx)
- }
- return schema ?: null
- }
+ def schema = param.substring('currentSchema='.length())
+ return schema ?: null
}
}
-
- null
+ return null
}
}
(grails-core) 02/02: refactor: rename to `grails-testing-support-dbcleanup-*`
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
matrei pushed a commit to branch database-cleanup-feature-feedback
in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit 3dfc3d6544a147d83c41a3c24dcb1b6cadc456a1
Author: Mattias Reichel <ma...@gmail.com>
AuthorDate: Wed Feb 25 15:22:41 2026 +0100
refactor: rename to `grails-testing-support-dbcleanup-*`
---
gradle/publish-root-config.gradle | 6 +++---
grails-doc/src/en/guide/testing/integrationTesting.adoc | 8 ++++----
grails-test-examples/database-cleanup/build.gradle | 2 +-
.../README.md | 6 +++---
.../build.gradle | 0
.../grails/testing/cleanup/core/ApplicationContextResolver.groovy | 0
.../org/apache/grails/testing/cleanup/core/DatabaseCleaner.groovy | 0
.../org/apache/grails/testing/cleanup/core/DatabaseCleanup.groovy | 0
.../grails/testing/cleanup/core/DatabaseCleanupContext.groovy | 4 ++--
.../grails/testing/cleanup/core/DatabaseCleanupExtension.groovy | 0
.../grails/testing/cleanup/core/DatabaseCleanupInterceptor.groovy | 0
.../grails/testing/cleanup/core/DatabaseCleanupStats.groovy | 0
.../grails/testing/cleanup/core/DatasourceCleanupMapping.groovy | 0
.../testing/cleanup/core/DefaultApplicationContextResolver.groovy | 0
.../grails/testing/cleanup/core/TestContextHolderListener.groovy | 0
.../org.spockframework.runtime.extension.IGlobalExtension | 0
.../src/main/resources/META-INF/spring.factories | 0
.../grails/testing/cleanup/core/DatabaseCleanupContextSpec.groovy | 0
.../testing/cleanup/core/DatabaseCleanupExtensionSpec.groovy | 0
.../testing/cleanup/core/DatabaseCleanupInterceptorSpec.groovy | 0
.../grails/testing/cleanup/core/DatabaseCleanupStatsSpec.groovy | 0
.../testing/cleanup/core/DatasourceCleanupMappingSpec.groovy | 0
.../cleanup/core/DefaultApplicationContextResolverSpec.groovy | 0
.../README.md | 2 +-
.../build.gradle | 2 +-
.../org/apache/grails/testing/cleanup/h2/H2DatabaseCleaner.groovy | 0
.../grails/testing/cleanup/h2/H2DatabaseCleanupHelper.groovy | 0
.../org.apache.grails.testing.cleanup.core.DatabaseCleaner | 0
.../apache/grails/testing/cleanup/h2/H2DatabaseCleanerSpec.groovy | 0
.../grails/testing/cleanup/h2/H2DatabaseCleanupHelperSpec.groovy | 0
.../README.md | 2 +-
.../build.gradle | 2 +-
.../testing/cleanup/postgresql/PostgresDatabaseCleaner.groovy | 0
.../cleanup/postgresql/PostgresDatabaseCleanupHelper.groovy | 0
.../testing/cleanup/postgresql/PostgresContainerHolder.groovy | 0
.../postgresql/PostgresDatabaseCleanerFunctionalSpec.groovy | 0
.../testing/cleanup/postgresql/PostgresDatabaseCleanerSpec.groovy | 0
.../cleanup/postgresql/PostgresDatabaseCleanupHelperSpec.groovy | 0
settings.gradle | 6 +++---
39 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/gradle/publish-root-config.gradle b/gradle/publish-root-config.gradle
index b3eeb7fd4d..1b56b0ccb8 100644
--- a/gradle/publish-root-config.gradle
+++ b/gradle/publish-root-config.gradle
@@ -76,9 +76,9 @@ def publishedProjects = [
'grails-taglib',
'grails-test-core',
'grails-testing-support-core',
- 'grails-testing-support-cleanup-core',
- 'grails-testing-support-cleanup-h2',
- 'grails-testing-support-cleanup-postgresql',
+ 'grails-testing-support-dbcleanup-core',
+ 'grails-testing-support-dbcleanup-h2',
+ 'grails-testing-support-dbcleanup-postgresql',
'grails-testing-support-mongodb',
'grails-testing-support-views-gson',
'grails-testing-support-web',
diff --git a/grails-doc/src/en/guide/testing/integrationTesting.adoc b/grails-doc/src/en/guide/testing/integrationTesting.adoc
index 732f7be74e..d080dfda1e 100644
--- a/grails-doc/src/en/guide/testing/integrationTesting.adoc
+++ b/grails-doc/src/en/guide/testing/integrationTesting.adoc
@@ -154,12 +154,12 @@ Database cleanup is automatically discovered and applied based on your datasourc
====== H2 Database
-To use `@DatabaseCleanup` with H2 databases, add the `grails-testing-support-cleanup-h2` dependency:
+To use `@DatabaseCleanup` with H2 databases, add the `grails-testing-support-dbcleanup-h2` dependency:
[source,groovy]
----
dependencies {
- integrationTestImplementation 'org.apache.grails:grails-testing-support-cleanup-h2'
+ integrationTestImplementation 'org.apache.grails:grails-testing-support-dbcleanup-h2'
}
----
@@ -167,12 +167,12 @@ This module will clean up schema the specified schema by default, otherwise it w
====== PostgreSQL
-To use `@DatabaseCleanup` with PostgreSQL databases, add the `grails-testing-support-cleanup-postgresql` dependency:
+To use `@DatabaseCleanup` with PostgreSQL databases, add the `grails-testing-support-dbcleanup-postgresql` dependency:
[source,groovy]
----
dependencies {
- integrationTestImplementation 'org.apache.grails:grails-testing-support-cleanup-postgresql'
+ integrationTestImplementation 'org.apache.grails:grails-testing-support-dbcleanup-postgresql'
}
----
diff --git a/grails-test-examples/database-cleanup/build.gradle b/grails-test-examples/database-cleanup/build.gradle
index e88e4f8d3a..08324af9a4 100644
--- a/grails-test-examples/database-cleanup/build.gradle
+++ b/grails-test-examples/database-cleanup/build.gradle
@@ -44,7 +44,7 @@ dependencies {
runtimeOnly 'com.zaxxer:HikariCP'
integrationTestImplementation 'org.apache.grails.testing:grails-testing-support-core'
- integrationTestImplementation project(':grails-testing-support-cleanup-h2')
+ integrationTestImplementation project(':grails-testing-support-dbcleanup-h2')
}
apply {
diff --git a/grails-testing-support-cleanup-core/README.md b/grails-testing-support-dbcleanup-core/README.md
similarity index 94%
rename from grails-testing-support-cleanup-core/README.md
rename to grails-testing-support-dbcleanup-core/README.md
index 140a24e265..db1b6157c9 100644
--- a/grails-testing-support-cleanup-core/README.md
+++ b/grails-testing-support-dbcleanup-core/README.md
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
-## grails-testing-support-cleanup-core
+## grails-testing-support-dbcleanup-core
Provides the core database cleanup testing support for Grails integration tests, including the `@DatabaseCleanup` annotation and the `DatabaseCleaner` SPI.
@@ -22,7 +22,7 @@ Provides the core database cleanup testing support for Grails integration tests,
Database cleanup is automatically discovered and applied based on your datasource configuration. The following database implementations are available:
-#### H2 Database (`grails-testing-support-cleanup-h2`)
+#### H2 Database (`grails-testing-support-dbcleanup-h2`)
**Supported Driver**: H2 Database Engine
@@ -41,7 +41,7 @@ jdbc:h2:mem:testdb
jdbc:h2:file:/tmp/testdb
```
-#### PostgreSQL (`grails-testing-support-cleanup-postgresql`)
+#### PostgreSQL (`grails-testing-support-dbcleanup-postgresql`)
**Supported Driver**: PostgreSQL JDBC Driver
diff --git a/grails-testing-support-cleanup-core/build.gradle b/grails-testing-support-dbcleanup-core/build.gradle
similarity index 100%
rename from grails-testing-support-cleanup-core/build.gradle
rename to grails-testing-support-dbcleanup-core/build.gradle
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/ApplicationContextResolver.groovy b/grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/ApplicationContextResolver.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/ApplicationContextResolver.groovy
rename to grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/ApplicationContextResolver.groovy
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleaner.groovy b/grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleaner.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleaner.groovy
rename to grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleaner.groovy
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanup.groovy b/grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanup.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanup.groovy
rename to grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanup.groovy
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupContext.groovy b/grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupContext.groovy
similarity index 98%
rename from grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupContext.groovy
rename to grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupContext.groovy
index 10fdba73dd..8b276dbb36 100644
--- a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupContext.groovy
+++ b/grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupContext.groovy
@@ -129,7 +129,7 @@ class DatabaseCleanupContext {
throw new IllegalStateException(
'No DatabaseCleaner implementation found that supports ' +
"datasource '$beanName'. Ensure that a database-specific " +
- 'cleanup library (e.g., grails-testing-support-cleanup-h2) ' +
+ 'cleanup library (e.g., grails-testing-support-dbcleanup-h2) ' +
'is on the classpath for each database type used in your tests. ' +
"Available cleaners: ${cleanersByType.values()*.databaseType()}"
)
@@ -179,7 +179,7 @@ class DatabaseCleanupContext {
throw new IllegalStateException(
"No DatabaseCleaner implementation found that supports datasource '$dsName'. " +
'Ensure that a database-specific cleanup library ' +
- '(e.g., grails-testing-support-cleanup-h2) is on the classpath, ' +
+ '(e.g., grails-testing-support-dbcleanup-h2) is on the classpath, ' +
"or specify the database type explicitly: '$dsName:type'. " +
"Available cleaners: ${cleanersByType.values()*.databaseType()}"
)
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupExtension.groovy b/grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupExtension.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupExtension.groovy
rename to grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupExtension.groovy
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupInterceptor.groovy b/grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupInterceptor.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupInterceptor.groovy
rename to grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupInterceptor.groovy
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupStats.groovy b/grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupStats.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupStats.groovy
rename to grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupStats.groovy
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatasourceCleanupMapping.groovy b/grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatasourceCleanupMapping.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatasourceCleanupMapping.groovy
rename to grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DatasourceCleanupMapping.groovy
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DefaultApplicationContextResolver.groovy b/grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DefaultApplicationContextResolver.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DefaultApplicationContextResolver.groovy
rename to grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/DefaultApplicationContextResolver.groovy
diff --git a/grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/TestContextHolderListener.groovy b/grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/TestContextHolderListener.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/TestContextHolderListener.groovy
rename to grails-testing-support-dbcleanup-core/src/main/groovy/org/apache/grails/testing/cleanup/core/TestContextHolderListener.groovy
diff --git a/grails-testing-support-cleanup-core/src/main/resources/META-INF/services/org.spockframework.runtime.extension.IGlobalExtension b/grails-testing-support-dbcleanup-core/src/main/resources/META-INF/services/org.spockframework.runtime.extension.IGlobalExtension
similarity index 100%
rename from grails-testing-support-cleanup-core/src/main/resources/META-INF/services/org.spockframework.runtime.extension.IGlobalExtension
rename to grails-testing-support-dbcleanup-core/src/main/resources/META-INF/services/org.spockframework.runtime.extension.IGlobalExtension
diff --git a/grails-testing-support-cleanup-core/src/main/resources/META-INF/spring.factories b/grails-testing-support-dbcleanup-core/src/main/resources/META-INF/spring.factories
similarity index 100%
rename from grails-testing-support-cleanup-core/src/main/resources/META-INF/spring.factories
rename to grails-testing-support-dbcleanup-core/src/main/resources/META-INF/spring.factories
diff --git a/grails-testing-support-cleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupContextSpec.groovy b/grails-testing-support-dbcleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupContextSpec.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupContextSpec.groovy
rename to grails-testing-support-dbcleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupContextSpec.groovy
diff --git a/grails-testing-support-cleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupExtensionSpec.groovy b/grails-testing-support-dbcleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupExtensionSpec.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupExtensionSpec.groovy
rename to grails-testing-support-dbcleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupExtensionSpec.groovy
diff --git a/grails-testing-support-cleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupInterceptorSpec.groovy b/grails-testing-support-dbcleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupInterceptorSpec.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupInterceptorSpec.groovy
rename to grails-testing-support-dbcleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupInterceptorSpec.groovy
diff --git a/grails-testing-support-cleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupStatsSpec.groovy b/grails-testing-support-dbcleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupStatsSpec.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupStatsSpec.groovy
rename to grails-testing-support-dbcleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatabaseCleanupStatsSpec.groovy
diff --git a/grails-testing-support-cleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatasourceCleanupMappingSpec.groovy b/grails-testing-support-dbcleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatasourceCleanupMappingSpec.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatasourceCleanupMappingSpec.groovy
rename to grails-testing-support-dbcleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DatasourceCleanupMappingSpec.groovy
diff --git a/grails-testing-support-cleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DefaultApplicationContextResolverSpec.groovy b/grails-testing-support-dbcleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DefaultApplicationContextResolverSpec.groovy
similarity index 100%
rename from grails-testing-support-cleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DefaultApplicationContextResolverSpec.groovy
rename to grails-testing-support-dbcleanup-core/src/test/groovy/org/apache/grails/testing/cleanup/core/DefaultApplicationContextResolverSpec.groovy
diff --git a/grails-testing-support-cleanup-h2/README.md b/grails-testing-support-dbcleanup-h2/README.md
similarity index 95%
rename from grails-testing-support-cleanup-h2/README.md
rename to grails-testing-support-dbcleanup-h2/README.md
index d36c7a7bfd..b964fb5cff 100644
--- a/grails-testing-support-cleanup-h2/README.md
+++ b/grails-testing-support-dbcleanup-h2/README.md
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
-## grails-testing-support-cleanup-h2
+## grails-testing-support-dbcleanup-h2
Provides the H2 database cleanup implementation for the `DatabaseCleaner` SPI, enabling automatic table truncation in H2-backed integration tests.
diff --git a/grails-testing-support-cleanup-h2/build.gradle b/grails-testing-support-dbcleanup-h2/build.gradle
similarity index 97%
rename from grails-testing-support-cleanup-h2/build.gradle
rename to grails-testing-support-dbcleanup-h2/build.gradle
index e2d2e91312..2ca7d1db70 100644
--- a/grails-testing-support-cleanup-h2/build.gradle
+++ b/grails-testing-support-dbcleanup-h2/build.gradle
@@ -39,7 +39,7 @@ ext {
dependencies {
implementation platform(project(':grails-bom'))
- api project(':grails-testing-support-cleanup-core')
+ api project(':grails-testing-support-dbcleanup-core')
implementation 'org.springframework:spring-context'
implementation 'org.slf4j:slf4j-api'
implementation 'org.apache.groovy:groovy-sql'
diff --git a/grails-testing-support-cleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleaner.groovy b/grails-testing-support-dbcleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleaner.groovy
similarity index 100%
rename from grails-testing-support-cleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleaner.groovy
rename to grails-testing-support-dbcleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleaner.groovy
diff --git a/grails-testing-support-cleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanupHelper.groovy b/grails-testing-support-dbcleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanupHelper.groovy
similarity index 100%
rename from grails-testing-support-cleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanupHelper.groovy
rename to grails-testing-support-dbcleanup-h2/src/main/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanupHelper.groovy
diff --git a/grails-testing-support-cleanup-h2/src/main/resources/META-INF/services/org.apache.grails.testing.cleanup.core.DatabaseCleaner b/grails-testing-support-dbcleanup-h2/src/main/resources/META-INF/services/org.apache.grails.testing.cleanup.core.DatabaseCleaner
similarity index 100%
rename from grails-testing-support-cleanup-h2/src/main/resources/META-INF/services/org.apache.grails.testing.cleanup.core.DatabaseCleaner
rename to grails-testing-support-dbcleanup-h2/src/main/resources/META-INF/services/org.apache.grails.testing.cleanup.core.DatabaseCleaner
diff --git a/grails-testing-support-cleanup-h2/src/test/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanerSpec.groovy b/grails-testing-support-dbcleanup-h2/src/test/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanerSpec.groovy
similarity index 100%
rename from grails-testing-support-cleanup-h2/src/test/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanerSpec.groovy
rename to grails-testing-support-dbcleanup-h2/src/test/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanerSpec.groovy
diff --git a/grails-testing-support-cleanup-h2/src/test/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanupHelperSpec.groovy b/grails-testing-support-dbcleanup-h2/src/test/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanupHelperSpec.groovy
similarity index 100%
rename from grails-testing-support-cleanup-h2/src/test/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanupHelperSpec.groovy
rename to grails-testing-support-dbcleanup-h2/src/test/groovy/org/apache/grails/testing/cleanup/h2/H2DatabaseCleanupHelperSpec.groovy
diff --git a/grails-testing-support-cleanup-postgresql/README.md b/grails-testing-support-dbcleanup-postgresql/README.md
similarity index 95%
rename from grails-testing-support-cleanup-postgresql/README.md
rename to grails-testing-support-dbcleanup-postgresql/README.md
index ef44ef9499..fdeec12b64 100644
--- a/grails-testing-support-cleanup-postgresql/README.md
+++ b/grails-testing-support-dbcleanup-postgresql/README.md
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
-## grails-testing-support-cleanup-postgresql
+## grails-testing-support-dbcleanup-postgresql
Provides the PostgreSQL database cleanup implementation for the `DatabaseCleaner` SPI, enabling automatic table truncation in PostgreSQL-backed integration tests.
diff --git a/grails-testing-support-cleanup-postgresql/build.gradle b/grails-testing-support-dbcleanup-postgresql/build.gradle
similarity index 97%
rename from grails-testing-support-cleanup-postgresql/build.gradle
rename to grails-testing-support-dbcleanup-postgresql/build.gradle
index 15b977b2c1..0dc8365e19 100644
--- a/grails-testing-support-cleanup-postgresql/build.gradle
+++ b/grails-testing-support-dbcleanup-postgresql/build.gradle
@@ -38,7 +38,7 @@ ext {
dependencies {
implementation platform(project(':grails-bom'))
- api project(':grails-testing-support-cleanup-core')
+ api project(':grails-testing-support-dbcleanup-core')
implementation 'org.springframework:spring-context'
implementation 'org.slf4j:slf4j-api'
implementation 'org.apache.groovy:groovy-sql'
diff --git a/grails-testing-support-cleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleaner.groovy b/grails-testing-support-dbcleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleaner.groovy
similarity index 100%
rename from grails-testing-support-cleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleaner.groovy
rename to grails-testing-support-dbcleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleaner.groovy
diff --git a/grails-testing-support-cleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanupHelper.groovy b/grails-testing-support-dbcleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanupHelper.groovy
similarity index 100%
rename from grails-testing-support-cleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanupHelper.groovy
rename to grails-testing-support-dbcleanup-postgresql/src/main/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanupHelper.groovy
diff --git a/grails-testing-support-cleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresContainerHolder.groovy b/grails-testing-support-dbcleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresContainerHolder.groovy
similarity index 100%
rename from grails-testing-support-cleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresContainerHolder.groovy
rename to grails-testing-support-dbcleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresContainerHolder.groovy
diff --git a/grails-testing-support-cleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanerFunctionalSpec.groovy b/grails-testing-support-dbcleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanerFunctionalSpec.groovy
similarity index 100%
rename from grails-testing-support-cleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanerFunctionalSpec.groovy
rename to grails-testing-support-dbcleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanerFunctionalSpec.groovy
diff --git a/grails-testing-support-cleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanerSpec.groovy b/grails-testing-support-dbcleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanerSpec.groovy
similarity index 100%
rename from grails-testing-support-cleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanerSpec.groovy
rename to grails-testing-support-dbcleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanerSpec.groovy
diff --git a/grails-testing-support-cleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanupHelperSpec.groovy b/grails-testing-support-dbcleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanupHelperSpec.groovy
similarity index 100%
rename from grails-testing-support-cleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanupHelperSpec.groovy
rename to grails-testing-support-dbcleanup-postgresql/src/test/groovy/org/apache/grails/testing/cleanup/postgresql/PostgresDatabaseCleanupHelperSpec.groovy
diff --git a/settings.gradle b/settings.gradle
index 1357cc651b..ee920e9ec2 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -171,9 +171,9 @@ include(
// Testing Support
'grails-testing-support-datamapping',
- 'grails-testing-support-cleanup-core',
- 'grails-testing-support-cleanup-h2',
- 'grails-testing-support-cleanup-postgresql',
+ 'grails-testing-support-dbcleanup-core',
+ 'grails-testing-support-dbcleanup-h2',
+ 'grails-testing-support-dbcleanup-postgresql',
// Test Report
'grails-data-test-report',