HHH-18903 HHH-18904 Add test for issue

This commit is contained in:
Marco Belladelli 2024-12-04 11:39:52 +01:00
parent c21568f77c
commit 5b981404a2
1 changed files with 155 additions and 32 deletions

View File

@ -9,7 +9,10 @@ import jakarta.persistence.AccessType;
import jakarta.persistence.Basic; import jakarta.persistence.Basic;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import jakarta.persistence.Table; import jakarta.persistence.PostLoad;
import jakarta.persistence.PrePersist;
import jakarta.persistence.Transient;
import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl; import org.hibernate.bytecode.enhance.internal.bytebuddy.EnhancerImpl;
import org.hibernate.bytecode.enhance.spi.EnhancementContext; import org.hibernate.bytecode.enhance.spi.EnhancementContext;
import org.hibernate.bytecode.enhance.spi.EnhancementException; import org.hibernate.bytecode.enhance.spi.EnhancementException;
@ -18,11 +21,13 @@ import org.hibernate.bytecode.enhance.spi.UnsupportedEnhancementStrategy;
import org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState; import org.hibernate.bytecode.internal.bytebuddy.ByteBuddyState;
import org.hibernate.bytecode.spi.ByteCodeHelper; import org.hibernate.bytecode.spi.ByteCodeHelper;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext; import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext;
import org.hibernate.testing.orm.junit.Jira;
import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.JiraKey;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
@ -39,28 +44,31 @@ public class UnsupportedEnhancementStrategyTest {
return UnsupportedEnhancementStrategy.SKIP; return UnsupportedEnhancementStrategy.SKIP;
} }
}; };
byte[] originalBytes = getAsBytes( SomeEntity.class ); byte[] enhancedBytes = doEnhance( SomeEntity.class, context );
byte[] enhancedBytes = doEnhance( SomeEntity.class, originalBytes, context );
assertThat( enhancedBytes ).isNull(); // null means "not enhanced" assertThat( enhancedBytes ).isNull(); // null means "not enhanced"
} }
@Test @Test
public void fail() throws IOException { public void fail() throws IOException {
var context = new EnhancerTestContext() { var context = new UnsupportedEnhancerContext();
@Override assertThatThrownBy( () -> doEnhance( SomeEntity.class, context ) ).isInstanceOf( EnhancementException.class )
public UnsupportedEnhancementStrategy getUnsupportedEnhancementStrategy() {
return UnsupportedEnhancementStrategy.FAIL;
}
};
byte[] originalBytes = getAsBytes( SomeEntity.class );
assertThatThrownBy( () -> doEnhance( SomeEntity.class, originalBytes, context ) )
.isInstanceOf( EnhancementException.class )
.hasMessageContainingAll( .hasMessageContainingAll(
String.format( String.format(
"Enhancement of [%s] failed because no field named [%s] could be found for property accessor method [%s].", "Enhancement of [%s] failed because no field named [%s] could be found for property accessor method [%s].",
SomeEntity.class.getName(), "propertyMethod", "getPropertyMethod" ), SomeEntity.class.getName(),
"To fix this, make sure all property accessor methods have a matching field." "propertyMethod",
"getPropertyMethod"
), "To fix this, make sure all property accessor methods have a matching field."
); );
assertThatThrownBy( () -> doEnhance( SomeOtherEntity.class, context ) ).isInstanceOf( EnhancementException.class )
.hasMessageContainingAll(
String.format(
"Enhancement of [%s] failed because no field named [%s] could be found for property accessor method [%s].",
SomeOtherEntity.class.getName(),
"propertyMethod",
"setPropertyMethod"
), "To fix this, make sure all property accessor methods have a matching field."
);
} }
@Test @Test
@ -73,26 +81,49 @@ public class UnsupportedEnhancementStrategyTest {
return UnsupportedEnhancementStrategy.LEGACY; return UnsupportedEnhancementStrategy.LEGACY;
} }
}; };
byte[] originalBytes = getAsBytes( SomeEntity.class ); byte[] enhancedBytes = doEnhance( SomeEntity.class, context );
byte[] enhancedBytes = doEnhance( SomeEntity.class, originalBytes, context );
assertThat( enhancedBytes ).isNotNull(); // non-null means enhancement _was_ performed assertThat( enhancedBytes ).isNotNull(); // non-null means enhancement _was_ performed
} }
private byte[] doEnhance(Class<SomeEntity> someEntityClass, byte[] originalBytes, EnhancementContext context) { @Test
final ByteBuddyState byteBuddyState = new ByteBuddyState(); @Jira( "https://hibernate.atlassian.net/browse/HHH-18903" )
final Enhancer enhancer = new EnhancerImpl( context, byteBuddyState ); @Jira( "https://hibernate.atlassian.net/browse/HHH-18904" )
return enhancer.enhance( someEntityClass.getName(), originalBytes ); public void testEntityListeners() throws IOException {
// non-null means check passed and enhancement _was_ performed
assertThat( doEnhance( EventListenersEntity.class, new UnsupportedEnhancerContext() ) ).isNotNull();
} }
private byte[] getAsBytes(Class<?> clazz) throws IOException { @Test
@Jira( "https://hibernate.atlassian.net/browse/HHH-18903" )
@Jira( "https://hibernate.atlassian.net/browse/HHH-18904" )
public void testAccessTypeFieldEntity() throws IOException {
var context = new UnsupportedEnhancerContext();
// non-null means check passed and enhancement _was_ performed
assertThat( doEnhance( ExplicitAccessTypeFieldEntity.class, context ) ).isNotNull();
assertThat( doEnhance( ImplicitAccessTypeFieldEntity.class, context ) ).isNotNull();
}
private static byte[] doEnhance(Class<?> entityClass, EnhancementContext context) throws IOException {
final ByteBuddyState byteBuddyState = new ByteBuddyState();
final Enhancer enhancer = new EnhancerImpl( context, byteBuddyState );
return enhancer.enhance( entityClass.getName(), getAsBytes( entityClass ) );
}
private static byte[] getAsBytes(Class<?> clazz) throws IOException {
final String classFile = clazz.getName().replace( '.', '/' ) + ".class"; final String classFile = clazz.getName().replace( '.', '/' ) + ".class";
try (InputStream classFileStream = clazz.getClassLoader().getResourceAsStream( classFile )) { try (InputStream classFileStream = clazz.getClassLoader().getResourceAsStream( classFile )) {
return ByteCodeHelper.readByteCode( classFileStream ); return ByteCodeHelper.readByteCode( classFileStream );
} }
} }
@Entity static class UnsupportedEnhancerContext extends EnhancerTestContext {
@Table(name = "SOME_ENTITY") @Override
public UnsupportedEnhancementStrategy getUnsupportedEnhancementStrategy() {
return UnsupportedEnhancementStrategy.FAIL;
}
}
@Entity(name = "SomeEntity")
static class SomeEntity { static class SomeEntity {
@Id @Id
Long id; Long id;
@ -102,15 +133,6 @@ public class UnsupportedEnhancementStrategyTest {
String property; String property;
public SomeEntity() {
}
public SomeEntity(Long id, String field, String property) {
this.id = id;
this.field = field;
this.property = property;
}
/** /**
* The following property accessor methods are purposely named incorrectly to * The following property accessor methods are purposely named incorrectly to
* not match the "property" field. The HHH-16572 change ensures that * not match the "property" field. The HHH-16572 change ensures that
@ -128,4 +150,105 @@ public class UnsupportedEnhancementStrategyTest {
this.property = property; this.property = property;
} }
} }
@Entity(name = "SomeOtherEntity")
static class SomeOtherEntity {
@Id
Long id;
@Basic
String field;
String property;
@Access(AccessType.PROPERTY)
public void setPropertyMethod(String property) {
this.property = property;
}
}
@Entity(name = "EventListenersEntity")
static class EventListenersEntity {
private UUID id;
private String status = "new";
@Id
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
// special case, we should let it through
public UUID get() {
return id;
}
@PrePersist
public void setId() {
id = UUID.randomUUID();
}
@Transient
public String getState() {
return status;
}
@PostLoad
public void setState() {
status = "loaded";
}
@Transient
public boolean isLoaded() {
return status.equals( "loaded" );
}
}
@Entity(name = "ExplicitAccessTypeFieldEntity")
@Access( AccessType.FIELD )
static class ExplicitAccessTypeFieldEntity {
@Id
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long get() {
return id;
}
public String getSomething() {
return "something";
}
}
@Entity(name = "ImplicitAccessTypeFieldEntity")
static class ImplicitAccessTypeFieldEntity {
@Id
private Long id;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long get() {
return id;
}
public String getAnother() {
return "another";
}
}
} }