You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Thibault Kruse (JIRA)" <ji...@apache.org> on 2015/10/19 16:22:05 UTC

[jira] [Created] (GROOVY-7637) DefaultTypeTransformation.compareTo not symmetrical

Thibault Kruse created GROOVY-7637:
--------------------------------------

             Summary: DefaultTypeTransformation.compareTo not symmetrical
                 Key: GROOVY-7637
                 URL: https://issues.apache.org/jira/browse/GROOVY-7637
             Project: Groovy
          Issue Type: Bug
          Components: groovy-jdk
            Reporter: Thibault Kruse
            Priority: Minor


DefaultTypeTransformation.compareTo(Object left, Object right) is being used in plenty of places in Groovy.

However, for several corner cases, it does not provide symmetry, that is: when compareTo(a, b) returns a value (does not fail), then:

signum(compareTo(a, b)) == - signum(compareTo(b, a))

To reproduce:
{code}
  static class MyNumber extends Number {
        def n

        MyNumber(n) {
            this.n = n
        }

        int intValue(){n}
        long longValue(){n}
        float floatValue(){n}
        double doubleValue(){n}
        int hashCode(){-n}
        boolean equals(other) {
            if (other instanceof MyNumber) { return n==other.n}
            return false
        }
        String toString() {n.toString()}
    }

    static class MyNumberCompareTo extends MyNumber {

        MyNumberCompareTo(Object n) {
            super(n)
        }

        int compareTo(MyNumber other) {
            return n <=> other.n
        }
    }

    static class MyNumberComparable extends MyNumberCompareTo implements Comparable<MyNumber> {
        MyNumberComparable(Object n) {
            super(n)
        }

        int compareTo(Object other) {
            return n <=>  (MyNumber) other;
        }
    }

    void testCompareTo() {
        def object1 = new Object()
        def object2 = new Object()
        // objects
        assert compareTo(null, null) == 0
        assert compareTo(object1, null) == 1
        assert compareTo(null, object1) == -1
        assert compareTo(1, 1) == 0

        shouldFail(GroovyRuntimeException) {
            compareTo(object1, object2)
        }

        // chars, int values 49 and 50
        Character char1 = '1' as Character
        Character char2 = '2' as Character
        checkCompareToSymmetricSmallerThan(char1, char2)

        MyNumber number1 = new MyNumber(49)
        MyNumber number2 = new MyNumber(50)

        MyNumberCompareTo numCompTo1 = new MyNumberCompareTo(49)
        MyNumberCompareTo numCompTo2 = new MyNumberCompareTo(50)

        MyNumberComparable numComp1 = new MyNumberComparable(49)
        MyNumberComparable numComp2 = new MyNumberComparable(50)

        List lowers = [49, 49L, 49.0, 49.0G, 49.00G, char1, '1', number1, numCompTo1, numComp1]
        List highers = [50, 50L, 50.0, 50.0G, 50.00G, char2, '2', number2, numCompTo2, numComp2]

        lowers.each { def lower ->
            assert compareTo(lower, lower) == 0
            highers.each { def higher ->
                checkCompareToSymmetricSmallerThan(lower, higher)
            }
        }

        // glitch, failing with ClassCastException
        shouldFail(GroovyRuntimeException) {
            compareTo(1, "22")
        }
        shouldFail(GroovyRuntimeException) {
            compareTo("22", 1)
        }

        // strings and chars


        assert compareTo('aa1', '2' as Character) > 0
        // bug, classCast exception
        assert compareTo('2' as Character, 'aa1') < 0

        assert compareTo("aa${1}", '2' as Character) > 0
        // bug, classCast exception
        assert compareTo('2' as Character, "aa${1}") < 0

        // Strings and GStrings
        List lowers2 = ['aa1', "aa${1}"]
        List highers2 = ['bb2', "b${2}"]
        lowers2.each { def lower ->
            assert compareTo(lower, lower) == 0
            highers2.each { def higher ->
                checkCompareToSymmetricSmallerThan(lower, higher)
            }
        }
    }

    static void checkCompareToSymmetricSmallerThan(a, b) {
        try {
            assert compareTo(a, b) < 0
            assert compareTo(b, a) > 0
        } catch (AssertionError e) {
            System.err.print(a.class.toString() + ' compared to ' + b.class.toString() )
            throw e
        }
    }
{code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)