HHH-18903 HHH-18904 Add test for issue
This commit is contained in:
parent
c21568f77c
commit
5b981404a2
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue