junit-team / junit5

✅ The 5th major version of the programmer-friendly testing framework for Java and the JVM

Home Page:https://junit.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`@CsvSource` drops backslash character from input

xazap opened this issue · comments

I am seeing issues with backslash characters getting dropped while processing input from @CsvSource annotated tests. I observed that its occurrence depends on the test case that preceded it as is shown in the reproduction steps. I have considered it might be related to having single quote characters in the input so I deliberately set quoteCharacter='x' in the @CsvSource annotation.

Steps to reproduce

This test passes as expected:

@ParameterizedTest(name = "[{index}] {arguments}")
@CsvSource(useHeadersInDisplayName = true, delimiterString = "||", quoteCharacter = 'x', textBlock = """
	INPUT		|| EXPECTED LENGTH
	\\M\\\\o\\\'	|| 7
	\\M\\q\\\'	|| 6
""")
void test1(String input, int expectedLength) {
	Assertions.assertTrue(input.length() == expectedLength);
}

If I swap the input lines, the test unexpectedly fails because the String "\\M\\\\o\\\'" is missing a backslash character before 'o' resulting in a length of 6 and thus failing the test:

@ParameterizedTest(name = "[{index}] {arguments}")
@CsvSource(useHeadersInDisplayName = true, delimiterString = "||", quoteCharacter = 'x', textBlock = """
	INPUT		|| EXPECTED LENGTH
	\\M\\q\\\'	|| 6
	\\M\\\\o\\\'	|| 7
""")
void test2(String input, int expectedLength) {
	Assertions.assertTrue(input.length() == expectedLength);
}

To further show that a backlash character gets eaten, I added an extra '\\' character to the input. The test now passes, but note that the String "\\M\\\\\\o\\\'" should have a length of 8, not 7!

@ParameterizedTest(name = "[{index}] {arguments}")
@CsvSource(useHeadersInDisplayName = true, delimiterString = "||", quoteCharacter = 'x', textBlock = """
	INPUT		|| EXPECTED LENGTH
	\\M\\q\\\'	|| 6
	\\M\\\\\\o\\\'	|| 7
""")
void test3(String input, int expectedLength) {
	Assertions.assertTrue(input.length() == expectedLength);
}

Context

  • Jupiter version: 5.11.0-M1 (also tried: 5.10.2, same results)
  • Plaform version: 1.11.0-M1 (also tried: 1.10.2, same results)
  • Java 17
  • Build Tool/IDE: Maven 3.9.4 / Eclipse 2024.3

I've tried reproducing the issue with this test class:

package com.example.project;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class ParamEscapingTests {

    @ParameterizedTest(name = "[{index}] {arguments}")
    @CsvSource(useHeadersInDisplayName = true, delimiterString = "||", quoteCharacter = 'x', textBlock = """
        INPUT		    || EXPECTED LENGTH
        \\M\\\\o\\\'	|| 7
        \\M\\q\\\'	    || 6
    """)
    void test1(String input, int expectedLength) {
        assertEquals(expectedLength, input.length());
    }

    @ParameterizedTest(name = "[{index}] {arguments}")
    @CsvSource(useHeadersInDisplayName = true, delimiterString = "||", quoteCharacter = 'x', textBlock = """
        INPUT		    || EXPECTED LENGTH
        \\M\\q\\\'	    || 6
        \\M\\\\o\\\'	|| 7
    """)
    void test2(String input, int expectedLength) {
        assertEquals(expectedLength, input.length());
    }

    @ParameterizedTest(name = "[{index}] {arguments}")
    @CsvSource(useHeadersInDisplayName = true, delimiterString = "||", quoteCharacter = 'x', textBlock = """
        INPUT		    || EXPECTED LENGTH
        \\M\\q\\\'	    || 6
        \\M\\\\\\o\\\'	|| 7
    """)
    void test3(String input, int expectedLength) {
        assertEquals(expectedLength, input.length());
    }
}

However, for me all tests but the last pass as expected. I have tried with Maven and Gradle on Java 17.0.10. Not sure if Eclipse plays a part here. Are you using the Eclipse compiler or Maven? One thing IntelliJ flagged was the unnecessary escaping of ', meaning \\M\\\\o\\\' should be the same as \\M\\\\o\\'.

One thing IntelliJ flagged was the unnecessary escaping of ', meaning \\M\\\\o\\\' should be the same as \\M\\\\o\\'.

Ok, I tried in Eclipse now. The "unnecessary escaping" seems to be causing the issue when running from Eclipse. It works as expected after removing it.

I can confirm the tests pass except the last one when running a Maven build that is using the Oracle compiler. So it seems there is difference in behavior between Eclipse and Oracle compiler.

I can also conform that removing the "unnecessary escaping" fixes the problem when running in Eclipse. Still, the behaviour in Eclipse is weird. As far as I know escaping a quote is legal in a String. I might take this up with the ECJ project to see whether Eclipse compiler is actually parsing correctly. It does not seem like an issue with @CvsSource. Thanks for looking into this!