From 6b0d97eb4ee3c291beff944c3996f61172e009c7 Mon Sep 17 00:00:00 2001 From: Zhangmei Li Date: Sun, 24 Apr 2022 22:59:40 +0800 Subject: [PATCH 1/3] add Whitebox.setInternalFinalState() Change-Id: I2e2fd25d95dc3033ac1fa332fe6ed56b3c259758 --- .../baidu/hugegraph/testutil/Whitebox.java | 48 +++++++++++++++- .../hugegraph/testutil/WhiteboxTest.java | 55 +++++++++++++++++++ 2 files changed, 100 insertions(+), 3 deletions(-) diff --git a/hugegraph-common/src/main/java/com/baidu/hugegraph/testutil/Whitebox.java b/hugegraph-common/src/main/java/com/baidu/hugegraph/testutil/Whitebox.java index 0d7c7c426..b9473142e 100644 --- a/hugegraph-common/src/main/java/com/baidu/hugegraph/testutil/Whitebox.java +++ b/hugegraph-common/src/main/java/com/baidu/hugegraph/testutil/Whitebox.java @@ -22,6 +22,7 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.Objects; @@ -32,13 +33,18 @@ public class Whitebox { public static final char SEPARATOR = '.'; - public static void setInternalState(Object target, String fieldName, - Object value) { + public static void setInternalState(Object target, + String fieldName, Object value) { assert target != null; assert fieldName != null; int sep = fieldName.lastIndexOf(SEPARATOR); if (sep > 0) { - target = getInternalState(target, fieldName.substring(0, sep)); + String prefix = fieldName.substring(0, sep); + Object result = getInternalState(target, prefix); + E.checkArgument(result != null, + "Can't set value on null field: `%s.%s`", + target, prefix); + target = result; fieldName = fieldName.substring(sep + 1); } @@ -80,6 +86,42 @@ public static T getInternalState(Object target, String fieldName) { } } + public static void setInternalFinalState(Object target, + String fieldName, Object value) { + Class c = target instanceof Class ? + (Class) target : target.getClass(); + try { + Field field = c.getDeclaredField(fieldName); + + // Remove final like FieldUtils.removeFinalModifier() + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + int oldModifiers = field.getModifiers(); + int nonFinal = oldModifiers & ~Modifier.FINAL; + modifiersField.setInt(field, nonFinal); + + // Reset overrideFieldAccessor + Field overrideFAField = Field.class.getDeclaredField("overrideFieldAccessor"); + overrideFAField.setAccessible(true); + if (overrideFAField.get(field) != null) { + setInternalState(field, "overrideFieldAccessor", null); + } + + try { + field.setAccessible(true); + field.set(target, value); + } finally { + // Resume old modifiers (final) + modifiersField.setInt(field, oldModifiers); + } + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(String.format( + "Can't set value of '%s' against object '%s'", + fieldName, target), e); + } + } + private static Field getFieldFromHierarchy(Class clazz, String field) { Field f = getField(clazz, field); while (f == null && clazz != Object.class) { diff --git a/hugegraph-common/src/test/java/com/baidu/hugegraph/testutil/WhiteboxTest.java b/hugegraph-common/src/test/java/com/baidu/hugegraph/testutil/WhiteboxTest.java index 92ab1aff1..855c6adbd 100644 --- a/hugegraph-common/src/test/java/com/baidu/hugegraph/testutil/WhiteboxTest.java +++ b/hugegraph-common/src/test/java/com/baidu/hugegraph/testutil/WhiteboxTest.java @@ -75,6 +75,7 @@ public void testSetInternalState() { Whitebox.setInternalState(test1, "ivalue", 11); Assert.assertEquals(11, Whitebox.getInternalState(test1, "ivalue")); + Assert.assertEquals(11, test1.ivalue); Whitebox.setInternalState(test1, "test2.fvalue", 22f); Assert.assertEquals(22f, Whitebox.getInternalState(test1, @@ -97,6 +98,52 @@ public void testSetInternalState() { }); } + @Test + public void testSetInternalFinalState() { + Test1 test1 = newTest(); + Assert.assertEquals(1, test1.ivalueFinal); + + Whitebox.setInternalState(test1, "ivalueFinal", 2); + Assert.assertEquals(2, Whitebox.getInternalState(test1, "ivalueFinal")); + // FIXME: seems don't take effect!!! + Assert.assertEquals(1, test1.ivalueFinal); + + Whitebox.setInternalFinalState(test1, "ivalueFinal", 3); + Assert.assertEquals(3, Whitebox.getInternalState(test1, "ivalueFinal")); + // FIXME: seems don't take effect!!! + Assert.assertEquals(1, test1.ivalueFinal); + } + + @Test + public void testSetInternalStaticFinalState() { +// Assert.assertThrows(RuntimeException.class, () -> { +// Whitebox.setInternalState(Test4.class, "staticFinalValue", 11); +// }, e -> { +// Assert.assertContains("Can't set value of 'staticFinalValue'", +// e.getMessage()); +// }); + + Assert.assertEquals(1, Test4.staticFinalValue); + // Can only call at the first reflect time + Whitebox.setInternalFinalState(Test4.class, "staticFinalValue", 11); + Assert.assertEquals(11, Whitebox.getInternalState(Test4.class, + "staticFinalValue")); + + Whitebox.setInternalFinalState(Test4.class, "staticFinalValue", 12); + Assert.assertEquals(12, Whitebox.getInternalState(Test4.class, + "staticFinalValue")); + + // FIXME: seems don't take effect!!! + Assert.assertEquals(1, Test4.staticFinalValue); + + Assert.assertThrows(RuntimeException.class, () -> { + Whitebox.setInternalState(Test4.class, "staticFinalValue", 1); + }, e -> { + Assert.assertContains("Can't set value of 'staticFinalValue'", + e.getMessage()); + }); + } + @Test public void testInvokeStatic() { Assert.assertEquals(1, Whitebox.invokeStatic(Test1.class, "svalue")); @@ -159,7 +206,10 @@ private static Test1 newTest() { private static class Test1 { private static int staticValue = 1; + private int ivalue = 1; + private final int ivalueFinal = 1; + private Test2 test2; private TestSubClass test4; @@ -218,6 +268,11 @@ private String value() { } } + private static class Test4 { + + private static final int staticFinalValue = 1; + } + @SuppressWarnings("unused") private static class TestSubClass extends Test1 { From 0f2aef6910c1d0f40d1b6d90aa6ce62e1539387e Mon Sep 17 00:00:00 2001 From: Zhangmei Li Date: Sun, 24 Apr 2022 23:30:15 +0800 Subject: [PATCH 2/3] delete Whitebox.setInternalFinalState() method since ineffective Change-Id: I0497e1206b59131a219d2941237a7b3a6a46df6f --- .../baidu/hugegraph/testutil/Whitebox.java | 37 ----------------- .../hugegraph/testutil/WhiteboxTest.java | 40 ------------------- 2 files changed, 77 deletions(-) diff --git a/hugegraph-common/src/main/java/com/baidu/hugegraph/testutil/Whitebox.java b/hugegraph-common/src/main/java/com/baidu/hugegraph/testutil/Whitebox.java index b9473142e..826ab01e8 100644 --- a/hugegraph-common/src/main/java/com/baidu/hugegraph/testutil/Whitebox.java +++ b/hugegraph-common/src/main/java/com/baidu/hugegraph/testutil/Whitebox.java @@ -22,7 +22,6 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.Objects; @@ -86,42 +85,6 @@ public static T getInternalState(Object target, String fieldName) { } } - public static void setInternalFinalState(Object target, - String fieldName, Object value) { - Class c = target instanceof Class ? - (Class) target : target.getClass(); - try { - Field field = c.getDeclaredField(fieldName); - - // Remove final like FieldUtils.removeFinalModifier() - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - int oldModifiers = field.getModifiers(); - int nonFinal = oldModifiers & ~Modifier.FINAL; - modifiersField.setInt(field, nonFinal); - - // Reset overrideFieldAccessor - Field overrideFAField = Field.class.getDeclaredField("overrideFieldAccessor"); - overrideFAField.setAccessible(true); - if (overrideFAField.get(field) != null) { - setInternalState(field, "overrideFieldAccessor", null); - } - - try { - field.setAccessible(true); - field.set(target, value); - } finally { - // Resume old modifiers (final) - modifiersField.setInt(field, oldModifiers); - } - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(String.format( - "Can't set value of '%s' against object '%s'", - fieldName, target), e); - } - } - private static Field getFieldFromHierarchy(Class clazz, String field) { Field f = getField(clazz, field); while (f == null && clazz != Object.class) { diff --git a/hugegraph-common/src/test/java/com/baidu/hugegraph/testutil/WhiteboxTest.java b/hugegraph-common/src/test/java/com/baidu/hugegraph/testutil/WhiteboxTest.java index 855c6adbd..9afbd117d 100644 --- a/hugegraph-common/src/test/java/com/baidu/hugegraph/testutil/WhiteboxTest.java +++ b/hugegraph-common/src/test/java/com/baidu/hugegraph/testutil/WhiteboxTest.java @@ -107,41 +107,6 @@ public void testSetInternalFinalState() { Assert.assertEquals(2, Whitebox.getInternalState(test1, "ivalueFinal")); // FIXME: seems don't take effect!!! Assert.assertEquals(1, test1.ivalueFinal); - - Whitebox.setInternalFinalState(test1, "ivalueFinal", 3); - Assert.assertEquals(3, Whitebox.getInternalState(test1, "ivalueFinal")); - // FIXME: seems don't take effect!!! - Assert.assertEquals(1, test1.ivalueFinal); - } - - @Test - public void testSetInternalStaticFinalState() { -// Assert.assertThrows(RuntimeException.class, () -> { -// Whitebox.setInternalState(Test4.class, "staticFinalValue", 11); -// }, e -> { -// Assert.assertContains("Can't set value of 'staticFinalValue'", -// e.getMessage()); -// }); - - Assert.assertEquals(1, Test4.staticFinalValue); - // Can only call at the first reflect time - Whitebox.setInternalFinalState(Test4.class, "staticFinalValue", 11); - Assert.assertEquals(11, Whitebox.getInternalState(Test4.class, - "staticFinalValue")); - - Whitebox.setInternalFinalState(Test4.class, "staticFinalValue", 12); - Assert.assertEquals(12, Whitebox.getInternalState(Test4.class, - "staticFinalValue")); - - // FIXME: seems don't take effect!!! - Assert.assertEquals(1, Test4.staticFinalValue); - - Assert.assertThrows(RuntimeException.class, () -> { - Whitebox.setInternalState(Test4.class, "staticFinalValue", 1); - }, e -> { - Assert.assertContains("Can't set value of 'staticFinalValue'", - e.getMessage()); - }); } @Test @@ -268,11 +233,6 @@ private String value() { } } - private static class Test4 { - - private static final int staticFinalValue = 1; - } - @SuppressWarnings("unused") private static class TestSubClass extends Test1 { From 90ba84619e28dcea540bdb1cbd5dcf6aa47c0e65 Mon Sep 17 00:00:00 2001 From: Zhangmei Li Date: Sun, 24 Apr 2022 23:50:36 +0800 Subject: [PATCH 3/3] improve test case Change-Id: I49fc02ca5087d52e81611ab5bb65ae2911ccb12f --- .../hugegraph/testutil/WhiteboxTest.java | 43 +++++++++++++------ 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/hugegraph-common/src/test/java/com/baidu/hugegraph/testutil/WhiteboxTest.java b/hugegraph-common/src/test/java/com/baidu/hugegraph/testutil/WhiteboxTest.java index 9afbd117d..6375c0dcc 100644 --- a/hugegraph-common/src/test/java/com/baidu/hugegraph/testutil/WhiteboxTest.java +++ b/hugegraph-common/src/test/java/com/baidu/hugegraph/testutil/WhiteboxTest.java @@ -56,7 +56,7 @@ public void testGetInternalState() { Test1 test1 = newTest(); Assert.assertEquals(1, Whitebox.getInternalState(test1, "ivalue")); Assert.assertEquals(2f, Whitebox.getInternalState(test1, - "test2.fvalue")); + "test2.finalValue")); Assert.assertEquals("3", Whitebox.getInternalState(test1, "test2.test3.str")); @@ -65,7 +65,7 @@ public void testGetInternalState() { }); Assert.assertThrows(RuntimeException.class, () -> { - Whitebox.getInternalState(test1, "test2.fvalue2"); + Whitebox.getInternalState(test1, "test2.valueNotExist"); }); } @@ -77,9 +77,9 @@ public void testSetInternalState() { Assert.assertEquals(11, Whitebox.getInternalState(test1, "ivalue")); Assert.assertEquals(11, test1.ivalue); - Whitebox.setInternalState(test1, "test2.fvalue", 22f); + Whitebox.setInternalState(test1, "test2.finalValue", 22f); Assert.assertEquals(22f, Whitebox.getInternalState(test1, - "test2.fvalue")); + "test2.finalValue")); Whitebox.setInternalState(test1, "test2.test3.str", "33"); Assert.assertEquals("33", Whitebox.getInternalState(test1, @@ -90,23 +90,40 @@ public void testSetInternalState() { }); Assert.assertThrows(RuntimeException.class, () -> { - Whitebox.setInternalState(test1, "test2.fvalue2", 22f); + Whitebox.setInternalState(test1, "test2.valueNotExist", 22f); }); Assert.assertThrows(RuntimeException.class, () -> { - Whitebox.setInternalState(test1, "test2.fvalue", 22d); + Whitebox.setInternalState(test1, "test2.finalValue", 22d); + }); + + Assert.assertThrows(RuntimeException.class, () -> { + test1.test2 = null; + Whitebox.setInternalState(test1, "test2.finalValue", 22f); + }, e -> { + Assert.assertContains("Can't set value on null field", + e.getMessage()); }); } @Test public void testSetInternalFinalState() { Test1 test1 = newTest(); - Assert.assertEquals(1, test1.ivalueFinal); + Assert.assertEquals(1, test1.finalValue); + + Whitebox.setInternalState(test1, "finalValue", 2); + Assert.assertEquals(2, Whitebox.getInternalState(test1, "finalValue")); + + Whitebox.setInternalState(test1, "finalValue", 3); + Assert.assertEquals(3, Whitebox.getInternalState(test1, "finalValue")); + + Whitebox.setInternalState(test1, "test2.finalValue", 22f); + Assert.assertEquals(22f, Whitebox.getInternalState(test1, + "test2.finalValue")); - Whitebox.setInternalState(test1, "ivalueFinal", 2); - Assert.assertEquals(2, Whitebox.getInternalState(test1, "ivalueFinal")); // FIXME: seems don't take effect!!! - Assert.assertEquals(1, test1.ivalueFinal); + Assert.assertEquals(1, test1.finalValue); + Assert.assertEquals(2f, test1.test2.finalValue, 0f); } @Test @@ -173,7 +190,7 @@ private static class Test1 { private static int staticValue = 1; private int ivalue = 1; - private final int ivalueFinal = 1; + private final int finalValue = 1; private Test2 test2; private TestSubClass test4; @@ -211,11 +228,11 @@ private static int throwfunc2() throws Exception { private static class Test2 { private static int staticValue = 2; - private final float fvalue = 2; + private final float finalValue = 2f; private Test3 test3; private float value() { - return this.fvalue; + return this.finalValue; } private T value(T o) {