<?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>failure case</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>4</expected-linenumbers>
        <code><![CDATA[
public class Foo {
    public Foo getBar(Foo x) {
        Foo foo = new Foo();
        if (x != null && foo.getBar(foo).equals(x)) {}
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>different var, 'tis ok</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    public void bar(Foo x, Foo y) {
        Foo foo = new Foo();
        if (x != null && foo.equals(y)) {}
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>proper usage</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    public void bar(Foo x, Foo y) {
        if (x != null && x.equals(y)) {}
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>variation of correct usage</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    public void bar(String x, String y) {
        if (x != null && "Foo".equals(y)) {}
        if (y.equals(x)) {}
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>var is not used in equals() call</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    public static Foo A = new Foo();
    public void bar(String c) {
        String d = "bar";
        if (c != null && A.bar(c).equals(d)) {}
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>[ 1481051 ] false + UnusedNullCheckInEquals</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    public void bar(Foo[] o1, Foo[] o2) {
        if (o1 != null && o1[0] != null && o2[0].getName() != null && o2[0].getName().equals(o1[0].getName())) { }
        if (o1 != null && o2.equals(o1.getName())) { }
    }
    public String getName() { return ""; }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>shouldn't this fail? Yes, it should. Fixed it, so that method calls to equals on variables are considered, too.</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>3</expected-linenumbers>
        <code><![CDATA[
public class Foo {
    public void bar(String x, String y) {
        if (x != null && y.equals(x)) {}
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Arrays can't be compared directly but with Arrays.equals().</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import java.util.Arrays;

public class Foo {
    private static boolean isSame(Object[] a1, Object[] a2) {
        return a1 == a2 || (a1 != null && a2 != null && Arrays.equals(a1, a2));
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>False negative with another condition in the middle</description>
        <expected-problems>3</expected-problems>
        <expected-linenumbers>3,7,14</expected-linenumbers>
        <code><![CDATA[
public class Foo {
    private boolean matches(String thatString, Object other, Class<?> otherClass) {
        return thatString != null && otherClass == thatString.getClass() && other.equals(thatString);
    }

    private boolean matches_if(String thatString, Object other, Class<?> otherClass) {
        if (thatString != null && otherClass == thatString.getClass() && other.equals(thatString)) {
            return true;
        }
        return false;
    }

    private boolean matches_var(String thatString, Object other, Class<?> otherClass) {
        boolean result = thatString != null && otherClass == thatString.getClass() && other.equals(thatString);
        return result;
    }

    private boolean matchesCorrected(String thatString, Object other, Class<?> otherClass) {
        return thatString != null && otherClass == thatString.getClass() && thatString.equals(other);
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>False positive with string literals / constants</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private static final String CONST = "";

    private boolean test(String val) {
        return val != null && "".equals(val);
    }

    private boolean test_const(String val) {
        return val != null && CONST.equals(val);
    }
}
        ]]></code>
    </test-code>
</test-data>
