<?xml version="1.0" encoding="UTF-8"?>
<test-data
        xmlns="http://pmd.sourceforge.net/rule-tests"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">

    <test-code>
        <description>Default config reports on every type decl</description>
        <expected-problems>5</expected-problems>
        <code><![CDATA[
public class foo {
    public @interface Foo_Bar { }

    public enum $Enum$ { }

    interface café { }

    public abstract class tehehe { }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>This is ok</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class FooBar {
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Control annotation convention</description>
        <rule-property name="annotationPattern">[a-z][A-Za-z]*</rule-property>
        <expected-problems>1</expected-problems>
        <expected-messages>
            <message>The class name 'foo' doesn't match '[A-Z][a-zA-Z0-9]*'</message>
        </expected-messages>
        <code><![CDATA[
public class foo {

    @interface covfefe {
    }

}
        ]]></code>
    </test-code>

    <code-fragment id="utility-class"><![CDATA[
public class Foo {

    static final int ZERO = 0;

    static int bar() {
        return bar();
    }

    static class BarUtil {

        static final int ONE = 1;

    }
}
    ]]></code-fragment>

    <test-code>
        <description>Utility class convention (default) - #3563</description>
        <expected-problems>0</expected-problems>
        <code-ref id="utility-class"/>
    </test-code>

    <test-code>
        <description>Utility class convention</description>
        <rule-property name="utilityClassPattern">[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)</rule-property>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>1</expected-linenumbers>
        <expected-messages>
            <message>The utility class name 'Foo' doesn't match '[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)'</message>
        </expected-messages>
        <code-ref id="utility-class"/>
    </test-code>

    <test-code>
        <description>Class with only empty decls should not be a utility class</description>
        <rule-property name="utilityClassPattern">[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)</rule-property>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    ;;;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Class with some instance fields should not be a utility class</description>
        <rule-property name="utilityClassPattern">[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)</rule-property>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Position {
    final int x;
    final int y;


    private Position(int px, int py) {
        x = px;
        y = py;
    }

    static Position of(int px, int py) {
        new Position(px, py);
    }

}
        ]]></code>
    </test-code>

    <test-code>
        <description>Class with static initializer alone should not be a utility class</description>
        <rule-property name="utilityClassPattern">[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)</rule-property>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {

    static {
        // ugly side effects
    }

}
        ]]></code>
    </test-code>

    <test-code>
        <description>Class with instance initializer should not be a utility class</description>
        <rule-property name="utilityClassPattern">[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)</rule-property>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {

    {
        // ugly side effects
    }

    static final int ZERO = 0;


    static int bar() {
        return bar();
    }

}
        ]]></code>
    </test-code>

    <test-code>
        <description>Class with only static members except constructors should be a utility class</description>
        <rule-property name="utilityClassPattern">[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)</rule-property>
        <expected-problems>1</expected-problems>
        <expected-messages>
            <message>The utility class name 'Foo' doesn't match '[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)'</message>
        </expected-messages>
        <code><![CDATA[
public class Foo {

    private Foo() {
    }

    public Foo() {
        // This constructor shouldn't exist,
        // but we consider the class a utility class anyway
    }

    static final int ZERO = 0;


    static int bar() {
        return bar();
    }

}
        ]]></code>
    </test-code>

    <test-code>
        <description>Class with only constructors should not be a utility class</description>
        <rule-property name="utilityClassPattern">[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)</rule-property>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {

    private Foo() {
    }

}
        ]]></code>
    </test-code>

    <test-code>
        <description>Numbers should be allowed by default</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Md5Checksum {
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Class extending another class should not be utility class</description>
        <rule-property name="utilityClassPattern">[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)</rule-property>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class StringList extends java.util.ArrayList<String> {
    static StringList emptyList() {
        return new StringList();
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Class extending another class should not be utility class 2</description>
        <rule-property name="utilityClassPattern">[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)</rule-property>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
// I couldn't reproduce the original failure, but we can use another regression test.
public class MyException extends RuntimeException {
    public MyException(Exception exception) {
        super(exception);
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Class with only main method should not be utility class</description>
        <rule-property name="utilityClassPattern">[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)</rule-property>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class MyException {

    public static void main(String[] args) {
        // whitelisted
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Class with only main method should not be utility class - varargs case</description>
        <rule-property name="utilityClassPattern">[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)</rule-property>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class MyException {

    public static void main(String... args) {
        // whitelisted
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Class with main method and private static fields should not be utility class</description>
        <rule-property name="utilityClassPattern">[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)</rule-property>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class MyException {
    private static final String foo = "FOOO";

    public static void main(String[] args) {
        // whitelisted
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Utility class can have name constants</description>
        <rule-property name="utilityClassPattern">[A-Z][a-zA-Z0-9]+(Utils?|Helper|Constants)</rule-property>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class MyConstants {
    public static final String FOOO = "FOOO";

    private MyConstants() {
        // whitelisted
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>ClassCastException with records</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>5</expected-linenumbers>
        <expected-messages>
            <message>The record name 'badlyNamedInnerRecord' doesn't match '[A-Z][a-zA-Z0-9]*'</message>
        </expected-messages>
        <code><![CDATA[
public record MyRecordOk(boolean b) {
    public MyRecordOk {
    }

    record badlyNamedInnerRecord(int i) {
        public badlyNamedInnerRecord {
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Test class (JUnit3) #2867</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>2</expected-linenumbers>
        <code><![CDATA[
import junit.framework.TestCase;
public class Foo extends TestCase {
    public void testBar() { }
}
]]></code>
    </test-code>

    <test-code>
        <description>Test class (JUnit4) #2867</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>2</expected-linenumbers>
        <code><![CDATA[
import org.junit.Test;
public class Foo {
    @Test
    public void testBar() { }
}
]]></code>
    </test-code>

    <test-code>
        <description>Test class (JUnit5) #2867</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>2</expected-linenumbers>
        <code><![CDATA[
import org.junit.jupiter.api.Test;
class Foo {
    @Test
    void testBar() { }
}
]]></code>
    </test-code>

    <test-code>
        <description>Test class (JUnit5) correctly named #2867</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import org.junit.jupiter.api.Test;
class FooTest {
    @Test
    void testBar() { }
}
]]></code>
    </test-code>

    <test-code>
        <description>Test class (JUnit5) with non-default testClassPattern #2867</description>
        <rule-property name="testClassPattern">Test[A-Z][a-zA-Z0-9]*</rule-property>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import org.junit.jupiter.api.Test;
class TestFoo {
    @Test
    void testBar() { }
}
]]></code>
    </test-code>

    <test-code>
        <description>Test class (JUnit5, Parameterized) #2867</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>3</expected-linenumbers>
        <code><![CDATA[
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
class Foo {
    @ParameterizedTest
    @ValueSource(ints = {1})
    void testBar(int i) { }
}
]]></code>
    </test-code>

    <test-code>
        <description>Test class (TestNG) #2867</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>2</expected-linenumbers>
        <code><![CDATA[
import org.testng.annotations.Test;
public class Foo {
    @Test
    public void testBar() {}
}
]]></code>
    </test-code>

    <test-code>
        <description>Not a test class (despite its name) #2867</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class FooTest {
    public void testBar() { }
}
]]></code>
    </test-code>

    <test-code>
        <description>Don't consider nested classes #2867</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
class MyTests {
    @Test
    void firstCheck() {}

    @Nested
    class Reactor {
        @Test
        void secondCheck() {}
    }
}
]]></code>
    </test-code>

    <test-code>
        <description>TestCase should be a valid pattern by default #2867</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import junit.framework.TestCase;
public class ExampleTestCase extends TestCase { }
]]></code>
    </test-code>
    
    <test-code>
        <description>[java] ClassNamingConventions: interfaces are identified as abstract classes (regression in 7.0.0) #4881</description>
        <rule-property name="abstractClassPattern">Abstract[A-Z][a-zA-Z0-9]*</rule-property>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public interface TestInterface {
  void test();
}
]]></code>
    </test-code>
</test-data>
