Skip to content

Experiment: Add options to truncate data and evict cache in tests via SessionFactory extension #10380

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,14 @@
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.stat.Statistics;
import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced;
import org.hibernate.testing.orm.junit.ClearMode;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.Jira;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
Expand All @@ -43,7 +42,7 @@
@Setting(name = AvailableSettings.GENERATE_STATISTICS, value = "true"),
@Setting(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true")
})
@SessionFactory
@SessionFactory(dropData = ClearMode.AFTER_ALL, clearCache = ClearMode.BEFORE_EACH)
@BytecodeEnhanced(runNotEnhancedAsWell = true)
@Jira("https://hibernate.atlassian.net/browse/HHH-18872")
public class ConcreteProxyToOneSecondLevelCacheTest {
Expand Down Expand Up @@ -144,11 +143,6 @@ private static void assertCacheStats(final Statistics stats, final long hits, fi
assertThat( stats.getSecondLevelCachePutCount() ).isEqualTo( puts );
}

@BeforeEach
public void clearCache(SessionFactoryScope scope) {
scope.getSessionFactory().getCache().evictAllRegions();
}

@BeforeAll
public void setUp(SessionFactoryScope scope) {
scope.inTransaction( session -> {
Expand All @@ -160,11 +154,6 @@ public void setUp(SessionFactoryScope scope) {
} );
}

@AfterAll
public void tearDown(SessionFactoryScope scope) {
scope.getSessionFactory().getSchemaManager().truncateMappedObjects();
}

@Entity(name = "TestNode")
@Cacheable
@ConcreteProxy
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.testing.orm.junit;

import org.hibernate.Incubating;

@Incubating
public enum ClearMode {
BEFORE_EACH, AFTER_EACH, AFTER_ALL, NEVER
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.hibernate.Incubating;
import org.hibernate.Interceptor;
import org.hibernate.resource.jdbc.spi.StatementInspector;

Expand Down Expand Up @@ -56,4 +57,10 @@
boolean useCollectingStatementInspector() default false;

boolean applyCollectionsInDefaultFetchGroup() default true;

@Incubating
ClearMode dropData() default ClearMode.NEVER;
@Incubating
ClearMode clearCache() default ClearMode.NEVER;

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.transaction.TransactionUtil;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler;
Expand All @@ -46,7 +48,8 @@
* @author Steve Ebersole
*/
public class SessionFactoryExtension
implements TestInstancePostProcessor, BeforeEachCallback, TestExecutionExceptionHandler {
implements TestInstancePostProcessor, BeforeEachCallback, TestExecutionExceptionHandler,
AfterEachCallback, AfterAllCallback {

private static final Logger log = Logger.getLogger( SessionFactoryExtension.class );
private static final String SESSION_FACTORY_KEY = SessionFactoryScope.class.getName();
Expand Down Expand Up @@ -92,13 +95,16 @@ public void beforeEach(ExtensionContext context) {
if ( sfAnnRef.isEmpty() ) {
// assume the annotations are defined on the class-level...
// will be validated by the parameter-resolver or SFS-extension
cleanup( context, ClearMode.BEFORE_EACH );
return;
}

final DomainModelScope domainModelScope = DomainModelExtension.resolveForMethodLevelSessionFactoryScope( context );
final SessionFactoryScope created = createSessionFactoryScope( context.getRequiredTestInstance(), sfAnnRef, domainModelScope, context );
final ExtensionContext.Store extensionStore = locateExtensionStore( context.getRequiredTestInstance(), context );
extensionStore.put( SESSION_FACTORY_KEY, created );

cleanup( context, ClearMode.BEFORE_EACH );
}

private static ExtensionContext.Store locateExtensionStore(Object testInstance, ExtensionContext context) {
Expand All @@ -111,6 +117,8 @@ private static SessionFactoryScopeImpl createSessionFactoryScope(
DomainModelScope domainModelScope,
ExtensionContext context) {
SessionFactoryProducer producer = null;
ClearMode dropDataMode = ClearMode.NEVER;
ClearMode clearCacheMode = ClearMode.NEVER;

if ( testInstance instanceof SessionFactoryProducer ) {
producer = (SessionFactoryProducer) testInstance;
Expand All @@ -122,6 +130,8 @@ private static SessionFactoryScopeImpl createSessionFactoryScope(

if ( sfAnnRef.isPresent() ) {
final SessionFactory sessionFactoryConfig = sfAnnRef.get();
dropDataMode = sessionFactoryConfig.dropData();
clearCacheMode = sessionFactoryConfig.clearCache();

producer = model -> {
try {
Expand Down Expand Up @@ -166,7 +176,7 @@ else if ( ! explicitInspectorClass.equals( StatementInspector.class ) ) {
throw new IllegalStateException( "Could not determine SessionFactory producer" );
}

final SessionFactoryScopeImpl sfScope = new SessionFactoryScopeImpl( domainModelScope, producer );
final SessionFactoryScopeImpl sfScope = new SessionFactoryScopeImpl( domainModelScope, producer, dropDataMode, clearCacheMode );

if ( testInstance instanceof SessionFactoryScopeAware ) {
( (SessionFactoryScopeAware) testInstance ).injectSessionFactoryScope( sfScope );
Expand Down Expand Up @@ -232,18 +242,42 @@ public void handleTestExecutionException(ExtensionContext context, Throwable thr
throw throwable;
}

@Override
public void afterAll(ExtensionContext context) {
cleanup( context, ClearMode.AFTER_ALL );
}

@Override
public void afterEach(ExtensionContext context) {
cleanup( context, ClearMode.AFTER_EACH );
}

private void cleanup(ExtensionContext context, ClearMode dropDataMode) {
final Object testInstance = context.getRequiredTestInstance();
final ExtensionContext.Store store = locateExtensionStore( testInstance, context );
final SessionFactoryScopeImpl scope = (SessionFactoryScopeImpl) store.get( SESSION_FACTORY_KEY );
if (scope != null ) {
scope.dropData( dropDataMode );
scope.clearCache( dropDataMode );
}
}

private static class SessionFactoryScopeImpl implements SessionFactoryScope, ExtensionContext.Store.CloseableResource {
private final DomainModelScope modelScope;
private final SessionFactoryProducer producer;
private final ClearMode dropDataMode;
private final ClearMode clearCacheMode;

private SessionFactoryImplementor sessionFactory;
private boolean active = true;

private SessionFactoryScopeImpl(
DomainModelScope modelScope,
SessionFactoryProducer producer) {
SessionFactoryProducer producer, ClearMode dropDataMode, ClearMode clearCacheMode) {
this.modelScope = modelScope;
this.producer = producer;
this.dropDataMode = dropDataMode;
this.clearCacheMode = clearCacheMode;
}

@Override
Expand Down Expand Up @@ -416,5 +450,17 @@ public void dropData() {
sessionFactory.getSchemaManager().truncateMappedObjects();
}
}

void dropData(ClearMode dropDataMode) {
if ( this.dropDataMode == dropDataMode ) {
dropData();
}
}

void clearCache(ClearMode clearCacheMode) {
if ( this.clearCacheMode == clearCacheMode ) {
sessionFactory.getCache().evictAllRegions();
}
}
}
}