You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "Paul King (JIRA)" <ji...@apache.org> on 2016/07/25 09:17:20 UTC
[jira] [Resolved] (GROOVY-7637) DefaultTypeTransformation.compareTo
not symmetrical
[ https://issues.apache.org/jira/browse/GROOVY-7637?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Paul King resolved GROOVY-7637.
-------------------------------
Resolution: Fixed
Assignee: Paul King
Fix Version/s: 2.5.0-beta-1
PR merged with some minor tweaks. Thanks!
> 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
> Assignee: Paul King
> Priority: Minor
> Fix For: 2.5.0-beta-1
>
>
> 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)