Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression: Parameterized test written in Kotlin fails after upgrade to v5.4.0 #1836

Closed
ChristianSchwarz opened this issue Mar 27, 2019 · 7 comments

Comments

@ChristianSchwarz
Copy link

ChristianSchwarz commented Mar 27, 2019

After upgrading from 5.3.1 to 5.4.0 the following Kotlin test failes.

Note: The Kotlin version (1.3.21) have not been change .

import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource


object Test {
    @JvmStatic
    fun data() = arrayOf(
            arrayOf("A", 1),
            arrayOf("B", 2),
            arrayOf("C", 3),
            arrayOf("", 4),
            arrayOf(null, 5) //null is a problem
    )

    @ParameterizedTest
    @MethodSource("securityLevels")
    fun securityLevelMappingTest(char: String, number: Integer) {

    }
}

Fails with Exception:

org.junit.platform.commons.JUnitException: The display name pattern defined for the parameterized test is invalid. See nested exception for further details.
Full Stacktrace
org.junit.platform.commons.JUnitException: The display name pattern defined for the parameterized test is invalid. See nested exception for further details.
        at org.junit.jupiter.params.ParameterizedTestNameFormatter.format(ParameterizedTestNameFormatter.java:46)
	at org.junit.jupiter.params.ParameterizedTestInvocationContext.getDisplayName(ParameterizedTestInvocationContext.java:38)
	at org.junit.jupiter.engine.descriptor.TestTemplateInvocationTestDescriptor.<init>(TestTemplateInvocationTestDescriptor.java:44)
	at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.createInvocationTestDescriptor(TestTemplateTestDescriptor.java:128)
	at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.lambda$execute$1(TestTemplateTestDescriptor.java:101)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.util.stream.ReferencePipeline$11$1.accept(ReferencePipeline.java:373)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
	at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:270)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
	at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:270)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1376)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
	at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:270)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1376)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
	at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
	at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.execute(TestTemplateTestDescriptor.java:104)
	at org.junit.jupiter.engine.descriptor.TestTemplateTestDescriptor.execute(TestTemplateTestDescriptor.java:40)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at java.util.ArrayList.forEach(ArrayList.java:1251)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at java.util.ArrayList.forEach(ArrayList.java:1251)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:74)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.ArrayStoreException: java.lang.String
	at org.junit.jupiter.params.ParameterizedTestNameFormatter.makeReadable(ParameterizedTestNameFormatter.java:79)
	at org.junit.jupiter.params.ParameterizedTestNameFormatter.formatSafely(ParameterizedTestNameFormatter.java:53)
	at org.junit.jupiter.params.ParameterizedTestNameFormatter.format(ParameterizedTestNameFormatter.java:41)
	... 83 more
@sormuras
Copy link
Member

@sormuras
Copy link
Member

sormuras commented Mar 27, 2019

Mh, I can't reproduce it on master using Gradle and IDEA. Is it possible that your test run includes multiple versions of junit-jupiter-params?

See d35b0a1 for a working example using master/SNAPSHOT version of JUnit Jupiter.

@ChristianSchwarz
Copy link
Author

ChristianSchwarz commented Mar 27, 2019

I think you can't reproduce the issue because my example is wrong. I reduced it too much from my original test.

Can you try it with the following data?

    @JvmStatic
    fun data() = arrayOf(
            arrayOf("A", 1),
            arrayOf("B", 2),
            arrayOf("C", 3),
            arrayOf("", 4),
            arrayOf(null, 5) //null is a problem
    )

@sormuras
Copy link
Member

Ah! That changes everything. Can reproduce it now.

sormuras added a commit that referenced this issue Mar 27, 2019
Prior to this commit Arrays.copyOf() was used to create a human-readable
names for parameterized tests. That method preserves the underlying type
of the source array, which isn't always Object[]. But Object[] is
required within the makeReadable() method as it may assign an instance
of String to an index of the result array.

Now, a two step solution is implemented:
  - create a new Object[] with the appropriate size
  - copy elements to that array via System.arraycopy()

Fixes #1836
@sormuras sormuras added this to the 5.5 M2 milestone Mar 27, 2019
@sormuras sormuras self-assigned this Mar 27, 2019
@sormuras
Copy link
Member

With #1837 applied, it looks better now:

image

sormuras added a commit that referenced this issue Mar 27, 2019
Prior to this commit Arrays.copyOf() was used without specifying the
resulting array type in order to create a human-readable names for
parameterized tests. Now, type `Object[]` is passed as an argument to
ensure the resulting array may contain any valid instance, here an
instance of `String`.

Fixes #1836
sormuras added a commit that referenced this issue Mar 27, 2019
Prior to this commit Arrays.copyOf() was used without specifying the
resulting array type in order to create a human-readable names for
parameterized tests. Now, type `Object[]` is passed as an argument to
ensure the resulting array may contain any valid instance, here an
instance of `String`.

Fixes #1836
@ChristianSchwarz
Copy link
Author

Wow, that was fast! When will your fix land in a stable version?

@marcphilipp marcphilipp modified the milestones: 5.5 M2, 5.4.2 Mar 29, 2019
@marcphilipp
Copy link
Member

@ChristianSchwarz I'll release 5.4.2 tonight.

marcphilipp pushed a commit that referenced this issue Apr 7, 2019
marcphilipp pushed a commit that referenced this issue Apr 7, 2019
Prior to this commit Arrays.copyOf() was used without specifying the
resulting array type in order to create a human-readable names for
parameterized tests. Now, type `Object[]` is passed as an argument to
ensure the resulting array may contain any valid instance, here an
instance of `String`.

Fixes #1836
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants