HHH-14006 Test extended bytecode enhancement for mapped superclasses and entity superclasses

This commit is contained in:
Yoann Rodière 2020-05-11 14:09:40 +02:00 committed by Sanne Grinovero
parent 5c5b347614
commit 1a28fd419e
4 changed files with 175 additions and 100 deletions

View File

@ -8,7 +8,7 @@ package org.hibernate.test.bytecode.enhancement.basic;
import org.hibernate.engine.spi.ManagedEntity;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assert;
@ -20,7 +20,6 @@ import javax.persistence.Id;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
import static org.junit.Assert.assertArrayEquals;
@ -115,104 +114,6 @@ public class BasicEnhancementTest {
// --- //
public static class ObjectAttributeMarkerInterceptor implements PersistentAttributeInterceptor {
public static final Object READ_MARKER = new Object();
public static final Object WRITE_MARKER = new Object();
@Override
public boolean readBoolean(Object obj, String name, boolean oldValue) {
return oldValue;
}
@Override
public boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue) {
return newValue;
}
@Override
public byte readByte(Object obj, String name, byte oldValue) {
return oldValue;
}
@Override
public byte writeByte(Object obj, String name, byte oldValue, byte newValue) {
return newValue;
}
@Override
public char readChar(Object obj, String name, char oldValue) {
return oldValue;
}
@Override
public char writeChar(Object obj, String name, char oldValue, char newValue) {
return newValue;
}
@Override
public short readShort(Object obj, String name, short oldValue) {
return oldValue;
}
@Override
public short writeShort(Object obj, String name, short oldValue, short newValue) {
return newValue;
}
@Override
public int readInt(Object obj, String name, int oldValue) {
return oldValue;
}
@Override
public int writeInt(Object obj, String name, int oldValue, int newValue) {
return newValue;
}
@Override
public float readFloat(Object obj, String name, float oldValue) {
return oldValue;
}
@Override
public float writeFloat(Object obj, String name, float oldValue, float newValue) {
return newValue;
}
@Override
public double readDouble(Object obj, String name, double oldValue) {
return oldValue;
}
@Override
public double writeDouble(Object obj, String name, double oldValue, double newValue) {
return newValue;
}
@Override
public long readLong(Object obj, String name, long oldValue) {
return oldValue;
}
@Override
public long writeLong(Object obj, String name, long oldValue, long newValue) {
return newValue;
}
@Override
public Object readObject(Object obj, String name, Object oldValue) {
return READ_MARKER;
}
@Override
public Object writeObject(Object obj, String name, Object oldValue, Object newValue) {
return WRITE_MARKER;
}
}
// --- //
@Entity
private static class SimpleEntity {

View File

@ -2,10 +2,13 @@ package org.hibernate.test.bytecode.enhancement.basic;
import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext;
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -15,6 +18,9 @@ import javax.persistence.Version;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.checkDirtyTracking;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.clearDirtyTracking;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assume.assumeTrue;
/**
* @author Luis Barreiro
@ -54,11 +60,39 @@ public class InheritedTest {
checkDirtyTracking( bob, "rate", "oca" );
}
// Adapted from BasicEnhancementTest#basicExtendedEnhancementTest
@Test
@TestForIssue(jiraKey = "HHH-14006")
public void extendedEnhancementTest() {
// This test only works if lazy loading bytecode enhancement is enabled,
// otherwise extended bytecode enhancement does not do anything we can check.
assumeTrue( PersistentAttributeInterceptable.class.isAssignableFrom( Employee.class ) );
Employee entity = new Employee();
( (PersistentAttributeInterceptable) entity ).$$_hibernate_setInterceptor( new ObjectAttributeMarkerInterceptor() );
Object decoy = new Object();
// This accesses "anUnspecifiedObject" on a variable of type Employee,
// but "anUnspecifiedObject" is defined the superclass Person.
// Such "virtual" access used to break extended bytecode enhancement.
entity.anUnspecifiedObject = decoy;
Object gotByReflection = EnhancerTestUtils.getFieldByReflection( entity, "anUnspecifiedObject" );
assertNotSame( decoy, gotByReflection );
assertSame( ObjectAttributeMarkerInterceptor.WRITE_MARKER, gotByReflection );
Object gotByEnhancedDirectAccess = entity.anUnspecifiedObject;
assertNotSame( decoy, gotByEnhancedDirectAccess );
assertSame( ObjectAttributeMarkerInterceptor.READ_MARKER, gotByEnhancedDirectAccess );
}
// --- //
@Entity
private static abstract class Person {
Object anUnspecifiedObject;
@Id
String name;

View File

@ -2,10 +2,14 @@ package org.hibernate.test.bytecode.enhancement.basic;
import org.hibernate.bytecode.enhance.spi.DefaultEnhancementContext;
import org.hibernate.bytecode.enhance.spi.UnloadedClass;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.bytecode.enhancement.CustomEnhancementContext;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestContext;
import org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils;
import org.junit.Assume;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -16,6 +20,9 @@ import javax.persistence.Version;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.checkDirtyTracking;
import static org.hibernate.testing.bytecode.enhancement.EnhancerTestUtils.clearDirtyTracking;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assume.assumeTrue;
/**
* @author Luis Barreiro
@ -41,11 +48,39 @@ public class MappedSuperclassTest {
checkDirtyTracking( charles, "title", "oca" );
}
// Adapted from BasicEnhancementTest#basicExtendedEnhancementTest
@Test
@TestForIssue(jiraKey = "HHH-14006")
public void extendedEnhancementTest() {
// This test only works if lazy loading bytecode enhancement is enabled,
// otherwise extended bytecode enhancement does not do anything we can check.
assumeTrue( PersistentAttributeInterceptable.class.isAssignableFrom( Employee.class ) );
Employee entity = new Employee();
( (PersistentAttributeInterceptable) entity ).$$_hibernate_setInterceptor( new ObjectAttributeMarkerInterceptor() );
Object decoy = new Object();
// This accesses "name" on a variable of type Employee,
// but "anUnspecifiedObject" is defined the superclass Person.
// Such "virtual" access used to break extended bytecode enhancement.
entity.anUnspecifiedObject = decoy;
Object gotByReflection = EnhancerTestUtils.getFieldByReflection( entity, "anUnspecifiedObject" );
assertNotSame( decoy, gotByReflection );
assertSame( ObjectAttributeMarkerInterceptor.WRITE_MARKER, gotByReflection );
Object gotByEnhancedDirectAccess = entity.anUnspecifiedObject;
assertNotSame( decoy, gotByEnhancedDirectAccess );
assertSame( ObjectAttributeMarkerInterceptor.READ_MARKER, gotByEnhancedDirectAccess );
}
// --- //
@MappedSuperclass
private static class Person {
Object anUnspecifiedObject;
@Id
String name;

View File

@ -0,0 +1,105 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.bytecode.enhancement.basic;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
public class ObjectAttributeMarkerInterceptor implements PersistentAttributeInterceptor {
public static final Object READ_MARKER = new Object();
public static final Object WRITE_MARKER = new Object();
@Override
public boolean readBoolean(Object obj, String name, boolean oldValue) {
return oldValue;
}
@Override
public boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue) {
return newValue;
}
@Override
public byte readByte(Object obj, String name, byte oldValue) {
return oldValue;
}
@Override
public byte writeByte(Object obj, String name, byte oldValue, byte newValue) {
return newValue;
}
@Override
public char readChar(Object obj, String name, char oldValue) {
return oldValue;
}
@Override
public char writeChar(Object obj, String name, char oldValue, char newValue) {
return newValue;
}
@Override
public short readShort(Object obj, String name, short oldValue) {
return oldValue;
}
@Override
public short writeShort(Object obj, String name, short oldValue, short newValue) {
return newValue;
}
@Override
public int readInt(Object obj, String name, int oldValue) {
return oldValue;
}
@Override
public int writeInt(Object obj, String name, int oldValue, int newValue) {
return newValue;
}
@Override
public float readFloat(Object obj, String name, float oldValue) {
return oldValue;
}
@Override
public float writeFloat(Object obj, String name, float oldValue, float newValue) {
return newValue;
}
@Override
public double readDouble(Object obj, String name, double oldValue) {
return oldValue;
}
@Override
public double writeDouble(Object obj, String name, double oldValue, double newValue) {
return newValue;
}
@Override
public long readLong(Object obj, String name, long oldValue) {
return oldValue;
}
@Override
public long writeLong(Object obj, String name, long oldValue, long newValue) {
return newValue;
}
@Override
public Object readObject(Object obj, String name, Object oldValue) {
return READ_MARKER;
}
@Override
public Object writeObject(Object obj, String name, Object oldValue, Object newValue) {
return WRITE_MARKER;
}
}