[PATCH] Support enum params that override Object#toString()
Anuraag Agrawal
anuraaga at gmail.com
Tue Jan 16 10:54:15 UTC 2018
Hello - my CLA has been processed so I guess the patch is ready for a look.
Can anyone help with this?
Thanks,
- Anuraag
On Tue, Dec 26, 2017 at 7:15 PM, Anuraag Agrawal <anuraaga at gmail.com> wrote:
> Hi all,
>
> As discussed in http://mail.openjdk.java.net/pipermail/jmh-dev/2017-
> December/002678.html currently JMH does not handle enum params where the
> enum overrides toString when using the reflection or ASM generators. This
> is because the spec explicitly allows enums to override toString() to
> something that doesn't match the descriptor's name, but restoring the enum
> using valueOf can only happen with the descriptor's name.
>
> https://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html#toString()
>
> This patch changes use of toString() to name(), which is always guaranteed
> to be the descriptor's name and round-trippable.
>
> https://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html#name()
>
> The patch has been attached and inlined below, including a regression test
> which fails without the logic change.
>
> Note, I just signed and emailed the Oracle CLA, so it may take some time
> for that to get processed.
>
> Thanks. Patch follows
>
> # HG changeset patch
> # User Anuraag Agrawal <anuraaga at gmail.com>
> # Date 1512560148 -32400
> # Wed Dec 06 20:35:48 2017 +0900
> # Node ID 4eefe5751280399fdbde2df655d2dcf43f2de557
> # Parent 1ddf31f810a3100b9433c3fedf24615e85b1d1a7
> Use Enum.name() instead of Enum.toString() for determining the string
> value of enum params. Only Enum.name() is guaranteed to round-trip through
> Enum.valueOf during execution, the specification explicitly allows
> overriding toString() to something that will not round-trip.
>
> diff --git a/jmh-core-it/src/test/java/org/openjdk/jmh/it/params/EnumParamSequenceTest.java
> b/jmh-core-it/src/test/java/org/openjdk/jmh/it/params/
> EnumParamToStringOverridingTest.java
> copy from jmh-core-it/src/test/java/org/openjdk/jmh/it/params/
> EnumParamSequenceTest.java
> copy to jmh-core-it/src/test/java/org/openjdk/jmh/it/params/
> EnumParamToStringOverridingTest.java
> --- a/jmh-core-it/src/test/java/org/openjdk/jmh/it/params/
> EnumParamSequenceTest.java
> +++ b/jmh-core-it/src/test/java/org/openjdk/jmh/it/params/
> EnumParamToStringOverridingTest.java
> @@ -45,56 +45,32 @@
> @Warmup(iterations = 1, time = 100, timeUnit = TimeUnit.MICROSECONDS)
> @Fork(1)
> @State(Scope.Thread)
> -public class EnumParamSequenceTest {
> +public class EnumParamToStringOverridingTest {
>
> @Param({"VALUE_A", "VALUE_B", "VALUE_C"})
> public SampleEnumA a;
>
> - @Param({"VALUE_A", "VALUE_B", "VALUE_C"})
> - public SampleEnumB b;
> -
> @Benchmark
> public void test() {
> Fixtures.work();
> }
>
> @Test
> - public void full() throws RunnerException {
> + public void normal() throws RunnerException {
> Options opts = new OptionsBuilder()
> .include(Fixtures.getTestMask(this.getClass()))
> .shouldFailOnError(true)
> .build();
>
> - Assert.assertEquals(3 * 3, new Runner(opts).run().size());
> - }
> -
> - @Test
> - public void constrainedA() throws RunnerException {
> - Options opts = new OptionsBuilder()
> - .include(Fixtures.getTestMask(this.getClass()))
> - .shouldFailOnError(true)
> - .param("a", SampleEnumA.VALUE_A.name())
> - .build();
> -
> - Assert.assertEquals(1 * 3, new Runner(opts).run().size());
> - }
> -
> - @Test
> - public void constrainedB() throws RunnerException {
> - Options opts = new OptionsBuilder()
> - .include(Fixtures.getTestMask(this.getClass()))
> - .shouldFailOnError(true)
> - .param("b", SampleEnumB.VALUE_A.name())
> - .build();
> -
> - Assert.assertEquals(1*3, new Runner(opts).run().size());
> + Assert.assertEquals(3, new Runner(opts).run().size());
> }
>
> public enum SampleEnumA {
> - VALUE_A, VALUE_B, VALUE_C
> - }
> + VALUE_A, VALUE_B, VALUE_C;
>
> - public enum SampleEnumB {
> - VALUE_A, VALUE_B, VALUE_C
> + @Override
> + public String toString() {
> + return name().toLowerCase();
> + }
> }
> }
> diff --git a/jmh-generator-asm/src/main/java/org/openjdk/jmh/
> generators/asm/ASMClassInfo.java b/jmh-generator-asm/src/main/
> java/org/openjdk/jmh/generators/asm/ASMClassInfo.java
> --- a/jmh-generator-asm/src/main/java/org/openjdk/jmh/
> generators/asm/ASMClassInfo.java
> +++ b/jmh-generator-asm/src/main/java/org/openjdk/jmh/
> generators/asm/ASMClassInfo.java
> @@ -221,7 +221,7 @@
> try {
> Collection<String> res = new ArrayList<>();
> for (Object cnst : Class.forName(origQualifiedName,
> false, Thread.currentThread().getContextClassLoader()).getEnumConstants())
> {
> - res.add(cnst.toString());
> + res.add(((Enum<?>) cnst).name());
> }
> return res;
> } catch (ClassNotFoundException e) {
> diff --git a/jmh-generator-reflection/src/main/java/org/openjdk/jmh/
> generators/reflection/RFClassInfo.java b/jmh-generator-reflection/
> src/main/java/org/openjdk/jmh/generators/reflection/RFClassInfo.java
> --- a/jmh-generator-reflection/src/main/java/org/openjdk/jmh/
> generators/reflection/RFClassInfo.java
> +++ b/jmh-generator-reflection/src/main/java/org/openjdk/jmh/
> generators/reflection/RFClassInfo.java
> @@ -162,7 +162,7 @@
> public Collection<String> getEnumConstants() {
> Collection<String> res = new ArrayList<>();
> for (Object cnst : klass.getEnumConstants()) {
> - res.add(cnst.toString());
> + res.add(((Enum<?>) cnst).name());
> }
> return res;
> }
>
> - Anuraag
>
More information about the jmh-dev
mailing list