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)