Skip to content

Commit

Permalink
Correct result of != comparison against List, Set, Map (fixes #2639)
Browse files Browse the repository at this point in the history
Adds __ne__ method to JavaProxy{List, Set, Map}. Changes BaseSet __eq__
and __ne__ methods to use item by item comparison where needed. Some
minor improvements e.g. use entrySet for map comparison. Also refactors
methods for testing equality and inequality to be very similar across
JavaProxy{List, Set, Map}.

Adds test coverage of != comparisons to Java {List, Set, Map}, and
tests with more Java types, the comparions in both directions.

--HG--
extra : amend_source : c4b1212f099c499b8ed582a0a169323b4dfc7332
  • Loading branch information
jamesmudd committed Jul 11, 2018
1 parent fb1b8d5 commit 03e78a7
Show file tree
Hide file tree
Showing 8 changed files with 559 additions and 115 deletions.
125 changes: 106 additions & 19 deletions Lib/test/test_dict_jy.py
@@ -1,10 +1,14 @@
from test import test_support
from java.util import HashMap, Hashtable
import unittest
from collections import defaultdict
import test_dict

from java.util import HashMap, LinkedHashMap, Hashtable
from java.util.concurrent import ConcurrentHashMap


class DictInitTest(unittest.TestCase):

def testInternalSetitemInInit(self):
"""Test for http://jython.org/bugs/1816134
Expand Down Expand Up @@ -41,14 +45,17 @@ def testUnhashableKeys(self):
else:
self.fail("dict as dict key should raise TypeError")


class DictCmpTest(unittest.TestCase):
"Test for http://bugs.jython.org/issue1031"

def testDictCmp(self):
# 'Implicit' comparision of dicts against other types instances
# shouldn't raise exception:
self.assertNotEqual({}, '')
# The same, but explicitly calling __cmp__ should raise TypeError:
self.assertRaises(TypeError, {}.__cmp__, '')

def testDictDerivedCmp(self):
# With derived classes that doesn't override __cmp__, the behaviour
# should be the same that with dicts:
Expand Down Expand Up @@ -86,7 +93,9 @@ class yet_another_dict(derived_dict_with_custom_cmp): pass
self.assertEqual(derived_dict_with_custom_cmp(), '')
self.assertEqual(yet_another_dict(), '')


class DictMiscTest(unittest.TestCase):

def test_pop_key_error(self):
# tests http://bugs.jython.org/issue2247
with self.assertRaisesRegexp(KeyError, r"^1$"):
Expand All @@ -96,16 +105,18 @@ def test_pop_key_error(self):
with self.assertRaisesRegexp(KeyError, r"^frozenset\(\[\]\)$"):
{}.pop(frozenset())


class DerivedDictTest(unittest.TestCase):
"Tests for derived dict behaviour"

def test_raising_custom_key_error(self):
class CustomKeyError(KeyError):
pass
class DerivedDict(dict):
def __getitem__(self, key):
raise CustomKeyError("custom message")
self.assertRaises(CustomKeyError, lambda: DerivedDict()['foo'])

def test_issue1676(self):
#See http://bugs.jython.org/issue1676
x=defaultdict()
Expand All @@ -123,17 +134,20 @@ def test_big_dict(self):

class JavaIntegrationTest(unittest.TestCase):
"Tests for instantiating dicts from Java maps and hashtables"
def test_hashmap(self):
x = HashMap()

type2test = HashMap

def test_map(self):
x = self.type2test()
x.put('a', 1)
x.put('b', 2)
x.put('c', 3)
x.put((1,2), "xyz")
y = dict(x)
self.assertEqual(set(y.items()), set([('a', 1), ('b', 2), ('c', 3), ((1,2), "xyz")]))

def test_hashmap_builtin_pymethods(self):
x = HashMap()
def test_map_builtin_pymethods(self):
x = self.type2test()
x['a'] = 1
x[(1, 2)] = 'xyz'
self.assertEqual({tup for tup in x.iteritems()}, {('a', 1), ((1, 2), 'xyz')})
Expand All @@ -142,26 +156,96 @@ def test_hashmap_builtin_pymethods(self):
self.assertEqual(str(x), repr(x))
self.assertEqual(type(str(x)), type(repr(x)))

def test_hashtable_equal(self):
def test_equal(self):
for d in ({}, {1:2}):
x = Hashtable(d)
x = self.type2test(d)
self.assertEqual(x, d)
self.assertEqual(d, x)
self.assertEqual(x, HashMap(d))

def test_hashtable_remove(self):
x = Hashtable({})
def test_remove(self):
x = self.type2test({'a': 1})
del x['a']
self.assertEqual(x, {})

x = self.type2test({})
with self.assertRaises(KeyError):
del x[0]

def test_hashtable(self):
x = Hashtable()
x.put('a', 1)
x.put('b', 2)
x.put('c', 3)
x.put((1,2), "xyz")
y = dict(x)
self.assertEqual(set(y.items()), set([('a', 1), ('b', 2), ('c', 3), ((1,2), "xyz")]))
def test_equality_empty_dict(self):
jmap = self.type2test()
self.assertTrue(jmap == {})
self.assertTrue({} == jmap)

def test_equality_simple_dict(self):
jmap = self.type2test()
self.assertFalse({'a': 1} == jmap)
self.assertFalse(jmap == {'a': 1})

def test_equality_mixed_types_dict(self):
ref = {False:0, 'a':1, u'b':2L, 3:"3"}
alt = {0:False, u'a':True, 'b':2, 3:"3"}
self.assertEqual(ref, alt) # test assumption
jref = self.type2test(ref)
for v in [ref, alt, jref]:
self.assertTrue(jref == v)
self.assertTrue(v == jref)
self.assertTrue(jref == self.type2test(v))
self.assertTrue(self.type2test(v) == jref)

alt1 = ref.copy(); alt1['a'] = 2;
alt2 = ref.copy(); del alt2['a'];
alt3 = ref.copy(); alt3['c'] = [];
for v in [alt1, alt2, alt3, {}]:
self.assertFalse(jref == v)
self.assertFalse(v == jref)
self.assertFalse(jref == self.type2test(v))
self.assertFalse(self.type2test(v) == jref)

# Test for http://bugs.jython.org/issue2639
# This is to test the != comparisons between Java and Python maps/dict
def test_inequality_empty_dict(self):
jmap = self.type2test()
self.assertFalse(jmap != {})
self.assertFalse({} != jmap)

def test_inequality_simple_dict(self):
jmap = self.type2test()
self.assertTrue(jmap != {'a': 1})
self.assertTrue({'a': 1} != jmap)

def test_inequality_mixed_types_dict(self):
ref = {False:0, 'a':1, u'b':2L, 3:"3"}
alt = {0:False, u'a':True, 'b':2, 3:"3"}
self.assertEqual(ref, alt) # test assumption
jref = self.type2test(ref)
for v in [ref, alt, jref]:
self.assertFalse(jref != v)
self.assertFalse(v != jref)
self.assertFalse(jref != self.type2test(v))
self.assertFalse(self.type2test(v) != jref)

alt1 = ref.copy(); alt1['a'] = 2;
alt2 = ref.copy(); del alt2['a'];
alt3 = ref.copy(); alt3['c'] = [];
for v in [alt1, alt2, alt3, {}]:
self.assertTrue(jref != v)
self.assertTrue(v != jref)
self.assertTrue(jref != self.type2test(v))
self.assertTrue(self.type2test(v) != jref)


class JavaHashMapTest(JavaIntegrationTest):
type2test = HashMap

class JavaLinkedHashMapTest(JavaIntegrationTest):
type2test = LinkedHashMap

class JavaHashtableTest(JavaIntegrationTest):
type2test = Hashtable

class JavaConcurrentHashMapTest(JavaIntegrationTest):
type2test = HashMap


class JavaDictTest(test_dict.DictTest):
Expand Down Expand Up @@ -265,7 +349,10 @@ def test_main():
DictCmpTest,
DictMiscTest,
DerivedDictTest,
JavaIntegrationTest,
JavaHashMapTest,
JavaLinkedHashMapTest,
JavaConcurrentHashMapTest,
JavaHashtableTest,
JavaDictTest,
PyStringMapTest)

Expand Down
113 changes: 101 additions & 12 deletions Lib/test/test_list_jy.py
Expand Up @@ -6,9 +6,10 @@
import test_list

if test_support.is_jython:
from java.util import ArrayList
from java.util import ArrayList, LinkedList, Vector
from java.lang import Integer, String


class ListTestCase(unittest.TestCase):

def test_recursive_list_slices(self):
Expand Down Expand Up @@ -60,6 +61,7 @@ def test_big_list(self):
self.assertEqual(len(lst), 64000)
self.assertEqual(sum(lst), 2047968000)


class ThreadSafetyTestCase(unittest.TestCase):

def run_threads(self, f, num=10):
Expand Down Expand Up @@ -112,6 +114,7 @@ def tester():
self.assert_(lst[1] in (1,10))
self.run_threads(tester)


class ExtendedSliceTestCase(unittest.TestCase):
'''Really thrash extended slice operations on list.'''
type2test = list
Expand Down Expand Up @@ -228,17 +231,17 @@ def test_init(self):
self.assertEqual(a, b)

def test_extend_java_ArrayList(self):
jl = ArrayList([])
jl = self.type2test([])
jl.extend([1,2])
self.assertEqual(jl, ArrayList([1,2]))
jl.extend(ArrayList([3,4]))
self.assertEqual(jl, self.type2test([1,2]))
jl.extend(self.type2test([3,4]))
self.assertEqual(jl, [1,2,3,4])

def test_remove(self):
# Verifies that overloaded java.util.List#remove(int) method can still be used, but with Python index semantics
# http://bugs.jython.org/issue2456
jl = ArrayList(xrange(10, -1, -1)) # 10 .. 0, inclusive
jl.remove(0) # removes jl[-1] (=0)
jl = self.type2test(xrange(10, -1, -1)) # 10 .. 0, inclusive
jl.remove(0) # removes jl[-1] (=0)
self.assertEqual(jl, range(10, 0, -1)) # 10 .. 1
self.assertRaises(ValueError, jl.remove, Integer(0)) # j.l.Integer does not support __index__ - maybe it should!
jl.remove(0) # removes jl[0] (=10)
Expand All @@ -251,7 +254,7 @@ def test_remove(self):

a_to_z = list(chr(i) for i in xrange(ord('a'), ord('z') + 1))
b_to_z_by_2 = list(chr(i) for i in xrange(ord('b'), ord('z') + 1, 2))
jl = ArrayList(a_to_z)
jl = self.type2test(a_to_z)
for i in xrange(13):
jl.remove(i)
self.assertEqual(jl, b_to_z_by_2)
Expand All @@ -263,6 +266,90 @@ def test_concat(self):
self.assertEquals(lst+lst2, [1, 2, 3, 4, 5, 6])
self.assertEquals(lst2+lst, [4, 5, 6, 1, 2, 3])

def test_equality_empty_list(self):
jl = self.type2test()
self.assertTrue(jl == [])
self.assertTrue([] == jl)

def test_equality_simple_list(self):
jl = self.type2test()
self.assertFalse(jl == [1])
self.assertFalse([1] == jl)

def test_equality_mixed_types_list(self):
ref = [False, 1, 3**9, "3"]
alt = [0, True, 3L**9, u"3"]
self.assertEqual(ref, alt) # test assumption
jref = self.type2test(ref)

for v in [ref, alt, jref]:
self.assertTrue(jref == v)
self.assertTrue(v == jref)
self.assertTrue(jref == self.type2test(v))

alt = [False, 1, 2e4, "3"]
for v in [alt, ref[:-1], ref+[{}], []]:
self.assertFalse(jref == v)
self.assertFalse(v == jref)
self.assertFalse(jref == self.type2test(v))

# Test for http://bugs.jython.org/issue2639
# This is to test the != comparisons between Java and Python lists
def test_inequality_empty_list(self):
jl = self.type2test()
self.assertFalse(jl != [])
self.assertFalse([] != jl)

def test_inequality_simple_list(self):
jl = self.type2test()
self.assertTrue(jl != [1])
self.assertTrue([1] != jl)

def test_inequality_mixed_types_list(self):
ref = [False, 1, 3**9, "3"]
alt = [0, True, 3L**9, u"3"]
self.assertEqual(ref, alt) # test assumption
jref = self.type2test(ref)

for v in [ref, alt, jref]:
self.assertFalse(jref != v)
self.assertFalse(v != jref)
self.assertFalse(jref != self.type2test(v))

alt = [False, 1, 2e4, "3"]
for v in [alt, ref[:-1], ref+[{}], []]:
self.assertTrue(jref != v)
self.assertTrue(v != jref)
self.assertTrue(jref != self.type2test(v))


class JavaArrayListTestCase(JavaListTestCase):
type2test = ArrayList


class JavaLinkedListTestCase(JavaListTestCase):
type2test = LinkedList

@unittest.skip("Fails for LinkedList see http://bugs.jython.org/issue2645")
def test_pop(self):
pass

@unittest.skip("Seems to hang for linked list")
def test_bigrepeat(self):
pass

@unittest.skip("Takes a long time and can cause OutOfMemory")
def test_overflow(self):
pass


class JavaVectorTestCase(JavaListTestCase):
type2test = Vector

@unittest.skip("Takes a long time and can cause OutOfMemory")
def test_bigrepeat(self):
pass


class ListSubclassTestCase(unittest.TestCase):

Expand Down Expand Up @@ -305,11 +392,13 @@ def __getitem__(self, index):


def test_main():
test_support.run_unittest(ListSubclassTestCase,
ListTestCase,
test_support.run_unittest(ListTestCase,
ThreadSafetyTestCase,
ExtendedSliceTestCase,
JavaListTestCase)

JavaArrayListTestCase,
JavaLinkedListTestCase,
JavaVectorTestCase,
ListSubclassTestCase)

if __name__ == "__main__":
test_main()

0 comments on commit 03e78a7

Please sign in to comment.