diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/BasicEnhancementTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/BasicEnhancementTest.java index fbe4ef03af..fa07ca062c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/BasicEnhancementTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/BasicEnhancementTest.java @@ -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 { diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/InheritedTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/InheritedTest.java index 2a7cb8e17c..c38cc51679 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/InheritedTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/InheritedTest.java @@ -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; diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/MappedSuperclassTest.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/MappedSuperclassTest.java index d52b446892..1f11aece96 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/MappedSuperclassTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/MappedSuperclassTest.java @@ -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; diff --git a/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/ObjectAttributeMarkerInterceptor.java b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/ObjectAttributeMarkerInterceptor.java new file mode 100644 index 0000000000..4f4ed9f618 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/test/bytecode/enhancement/basic/ObjectAttributeMarkerInterceptor.java @@ -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; + } +}