[Python-checkins] python/dist/src/Lib/test test_richcmp.py,1.7,1.8

doerwalter@users.sourceforge.net doerwalter@users.sourceforge.net
Tue, 29 Apr 2003 14:31:22 -0700


Update of /cvsroot/python/python/dist/src/Lib/test
In directory sc8-pr-cvs1:/tmp/cvs-serv17153/Lib/test

Modified Files:
	test_richcmp.py 
Log Message:
Port test_richcmp.py to PyUnit. From SF patch #662807 which additional
tests and comments.


Index: test_richcmp.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/test/test_richcmp.py,v
retrieving revision 1.7
retrieving revision 1.8
diff -C2 -d -r1.7 -r1.8
*** test_richcmp.py	23 Jul 2002 19:04:00 -0000	1.7
--- test_richcmp.py	29 Apr 2003 21:31:18 -0000	1.8
***************
*** 1,5 ****
  # Tests for rich comparisons
  
! from test.test_support import TestFailed, verify, verbose
  
  class Number:
--- 1,8 ----
  # Tests for rich comparisons
  
! import unittest
! from test import test_support
! 
! import operator
  
  class Number:
***************
*** 27,34 ****
  
      def __cmp__(self, other):
!         raise TestFailed, "Number.__cmp__() should not be called"
  
      def __repr__(self):
!         return "Number(%s)" % repr(self.x)
  
  class Vector:
--- 30,37 ----
  
      def __cmp__(self, other):
!         raise test_support.TestFailed, "Number.__cmp__() should not be called"
  
      def __repr__(self):
!         return "Number(%r)" % (self.x, )
  
  class Vector:
***************
*** 53,60 ****
  
      def __cmp__(self, other):
!         raise TestFailed, "Vector.__cmp__() should not be called"
  
      def __repr__(self):
!         return "Vector(%s)" % repr(self.data)
  
      def __lt__(self, other):
--- 56,63 ----
  
      def __cmp__(self, other):
!         raise test_support.TestFailed, "Vector.__cmp__() should not be called"
  
      def __repr__(self):
!         return "Vector(%r)" % (self.data, )
  
      def __lt__(self, other):
***************
*** 83,261 ****
          return other
  
! operators = "<", "<=", "==", "!=", ">", ">="
! opmap = {}
! for op in operators:
!     opmap[op] = eval("lambda a, b: a %s b" % op)
  
! def testvector():
!     a = Vector(range(2))
!     b = Vector(range(3))
!     for op in operators:
!         try:
!             opmap[op](a, b)
!         except ValueError:
!             pass
!         else:
!             raise TestFailed, "a %s b for different length should fail" % op
!     a = Vector(range(5))
!     b = Vector(5 * [2])
!     for op in operators:
!         print "%23s %-2s %-23s -> %s" % (a, op, b, opmap[op](a, b))
!         print "%23s %-2s %-23s -> %s" % (a, op, b.data, opmap[op](a, b.data))
!         print "%23s %-2s %-23s -> %s" % (a.data, op, b, opmap[op](a.data, b))
!         try:
!             if opmap[op](a, b):
!                 raise TestFailed, "a %s b shouldn't be true" % op
!             else:
!                 raise TestFailed, "a %s b shouldn't be false" % op
!         except TypeError:
              pass
  
! def testop(a, b, op):
!     try:
!         ax = a.x
!     except AttributeError:
!         ax = a
!     try:
!         bx = b.x
!     except AttributeError:
!         bx = b
!     opfunc = opmap[op]
!     realoutcome = opfunc(ax, bx)
!     testoutcome = opfunc(a, b)
!     if realoutcome != testoutcome:
!         print "Error for", a, op, b, ": expected", realoutcome,
!         print "but got", testoutcome
! ##    else:
! ##        print a, op, b, "-->", testoutcome # and "true" or "false"
  
! def testit(a, b):
!     testop(a, b, "<")
!     testop(a, b, "<=")
!     testop(a, b, "==")
!     testop(a, b, "!=")
!     testop(a, b, ">")
!     testop(a, b, ">=")
  
! def basic():
!     for a in range(3):
!         for b in range(3):
!             testit(Number(a), Number(b))
!             testit(a, Number(b))
!             testit(Number(a), b)
  
! def tabulate(c1=Number, c2=Number):
!     for op in operators:
!         opfunc = opmap[op]
!         print
!         print "operator:", op
!         print
!         print "%9s" % "",
!         for b in range(3):
!             b = c2(b)
!             print "| %9s" % b,
!         print "|"
!         print '----------+-' * 4
!         for a in range(3):
!             a = c1(a)
!             print "%9s" % a,
!             for b in range(3):
!                 b = c2(b)
!                 print "| %9s" % opfunc(a, b),
!             print "|"
!         print '----------+-' * 4
!     print
!     print '*' * 50
  
! def misbehavin():
!     class Misb:
!         def __lt__(self, other): return 0
!         def __gt__(self, other): return 0
!         def __eq__(self, other): return 0
!         def __le__(self, other): raise TestFailed, "This shouldn't happen"
!         def __ge__(self, other): raise TestFailed, "This shouldn't happen"
!         def __ne__(self, other): raise TestFailed, "This shouldn't happen"
!         def __cmp__(self, other): raise RuntimeError, "expected"
!     a = Misb()
!     b = Misb()
!     verify((a<b) == 0)
!     verify((a==b) == 0)
!     verify((a>b) == 0)
!     try:
!         print cmp(a, b)
!     except RuntimeError:
!         pass
!     else:
!         raise TestFailed, "cmp(Misb(), Misb()) didn't raise RuntimeError"
  
! def recursion():
!     from UserList import UserList
!     a = UserList(); a.append(a)
!     b = UserList(); b.append(b)
!     def check(s, a=a, b=b):
!         if verbose:
!             print "check", s
!         try:
!             if not eval(s):
!                 raise TestFailed, s + " was false but expected to be true"
!         except RuntimeError, msg:
!             raise TestFailed, str(msg)
!     if verbose:
!         print "recursion tests: a=%s, b=%s" % (a, b)
!     check('a==b')
!     check('not a!=b')
!     a.append(1)
!     if verbose:
!         print "recursion tests: a=%s, b=%s" % (a, b)
!     check('a!=b')
!     check('not a==b')
!     b.append(0)
!     if verbose:
!         print "recursion tests: a=%s, b=%s" % (a, b)
!     check('a!=b')
!     check('not a==b')
!     a[1] = -1
!     if verbose:
!         print "recursion tests: a=%s, b=%s" % (a, b)
!     check('a!=b')
!     check('not a==b')
!     if verbose: print "recursion tests ok"
  
! def dicts():
!     # Verify that __eq__ and __ne__ work for dicts even if the keys and
!     # values don't support anything other than __eq__ and __ne__.  Complex
!     # numbers are a fine example of that.
!     import random
!     imag1a = {}
!     for i in range(50):
!         imag1a[random.randrange(100)*1j] = random.randrange(100)*1j
!     items = imag1a.items()
!     random.shuffle(items)
!     imag1b = {}
!     for k, v in items:
!         imag1b[k] = v
!     imag2 = imag1b.copy()
!     imag2[k] = v + 1.0
!     verify(imag1a == imag1a, "imag1a == imag1a should have worked")
!     verify(imag1a == imag1b, "imag1a == imag1b should have worked")
!     verify(imag2 == imag2, "imag2 == imag2 should have worked")
!     verify(imag1a != imag2, "imag1a != imag2 should have worked")
!     for op in "<", "<=", ">", ">=":
!         try:
!             eval("imag1a %s imag2" % op)
!         except TypeError:
              pass
!         else:
!             raise TestFailed("expected TypeError from imag1a %s imag2" % op)
  
! def main():
!     basic()
!     tabulate()
!     tabulate(c1=int)
!     tabulate(c2=int)
!     testvector()
!     misbehavin()
!     recursion()
!     dicts()
  
! main()
--- 86,358 ----
          return other
  
! opmap = {
!     "lt": (lambda a,b: a< b, operator.lt, operator.__lt__),
!     "le": (lambda a,b: a<=b, operator.le, operator.__le__),
!     "eq": (lambda a,b: a==b, operator.eq, operator.__eq__),
!     "ne": (lambda a,b: a!=b, operator.ne, operator.__ne__),
!     "gt": (lambda a,b: a> b, operator.gt, operator.__gt__),
!     "ge": (lambda a,b: a>=b, operator.ge, operator.__ge__)
! }
  
! class VectorTest(unittest.TestCase):
! 
!     def checkfail(self, error, opname, *args):
!         for op in opmap[opname]:
!             self.assertRaises(error, op, *args)
! 
!     def checkequal(self, opname, a, b, expres):
!         for op in opmap[opname]:
!             realres = op(a, b)
!             # can't use assertEqual(realres, expres) here
!             self.assertEqual(len(realres), len(expres))
!             for i in xrange(len(realres)):
!                 # results are bool, so we can use "is" here
!                 self.assert_(realres[i] is expres[i])
! 
!     def test_mixed(self):
!         # check that comparisons involving Vector objects
!         # which return rich results (i.e. Vectors with itemwise
!         # comparison results) work
!         a = Vector(range(2))
!         b = Vector(range(3))
!         # all comparisons should fail for different length
!         for opname in opmap:
!             self.checkfail(ValueError, opname, a, b)
! 
!         a = range(5)
!         b = 5 * [2]
!         # try mixed arguments (but not (a, b) as that won't return a bool vector)
!         args = [(a, Vector(b)), (Vector(a), b), (Vector(a), Vector(b))]
!         for (a, b) in args:
!             self.checkequal("lt", a, b, [True,  True,  False, False, False])
!             self.checkequal("le", a, b, [True,  True,  True,  False, False])
!             self.checkequal("eq", a, b, [False, False, True,  False, False])
!             self.checkequal("ne", a, b, [True,  True,  False, True,  True ])
!             self.checkequal("gt", a, b, [False, False, False, True,  True ])
!             self.checkequal("ge", a, b, [False, False, True,  True,  True ])
! 
!             for ops in opmap.itervalues():
!                 for op in ops:
!                     # calls __nonzero__, which should fail
!                     self.assertRaises(TypeError, bool, op(a, b))
! 
! class NumberTest(unittest.TestCase):
! 
!     def test_basic(self):
!         # Check that comparisons involving Number objects
!         # give the same results give as comparing the
!         # corresponding ints
!         for a in xrange(3):
!             for b in xrange(3):
!                 for typea in (int, Number):
!                     for typeb in (int, Number):
!                         if typea==typeb==int:
!                             continue # the combination int, int is useless
!                         ta = typea(a)
!                         tb = typeb(b)
!                         for ops in opmap.itervalues():
!                             for op in ops:
!                                 realoutcome = op(a, b)
!                                 testoutcome = op(ta, tb)
!                                 self.assertEqual(realoutcome, testoutcome)
! 
!     def checkvalue(self, opname, a, b, expres):
!         for typea in (int, Number):
!             for typeb in (int, Number):
!                 ta = typea(a)
!                 tb = typeb(b)
!                 for op in opmap[opname]:
!                     realres = op(ta, tb)
!                     realres = getattr(realres, "x", realres)
!                     self.assert_(realres is expres)
! 
!     def test_values(self):
!         # check all operators and all comparison results
!         self.checkvalue("lt", 0, 0, False)
!         self.checkvalue("le", 0, 0, True )
!         self.checkvalue("eq", 0, 0, True )
!         self.checkvalue("ne", 0, 0, False)
!         self.checkvalue("gt", 0, 0, False)
!         self.checkvalue("ge", 0, 0, True )
! 
!         self.checkvalue("lt", 0, 1, True )
!         self.checkvalue("le", 0, 1, True )
!         self.checkvalue("eq", 0, 1, False)
!         self.checkvalue("ne", 0, 1, True )
!         self.checkvalue("gt", 0, 1, False)
!         self.checkvalue("ge", 0, 1, False)
! 
!         self.checkvalue("lt", 1, 0, False)
!         self.checkvalue("le", 1, 0, False)
!         self.checkvalue("eq", 1, 0, False)
!         self.checkvalue("ne", 1, 0, True )
!         self.checkvalue("gt", 1, 0, True )
!         self.checkvalue("ge", 1, 0, True )
! 
! class MiscTest(unittest.TestCase):
! 
!     def test_misbehavin(self):
!         class Misb:
!             def __lt__(self, other): return 0
!             def __gt__(self, other): return 0
!             def __eq__(self, other): return 0
!             def __le__(self, other): raise TestFailed, "This shouldn't happen"
!             def __ge__(self, other): raise TestFailed, "This shouldn't happen"
!             def __ne__(self, other): raise TestFailed, "This shouldn't happen"
!             def __cmp__(self, other): raise RuntimeError, "expected"
!         a = Misb()
!         b = Misb()
!         self.assertEqual(a<b, 0)
!         self.assertEqual(a==b, 0)
!         self.assertEqual(a>b, 0)
!         self.assertRaises(RuntimeError, cmp, a, b)
! 
!     def test_not(self):
!         # Check that exceptions in __nonzero__ are properly
!         # propagated by the not operator
!         import operator
!         class Exc:
              pass
+         class Bad:
+             def __nonzero__(self):
+                 raise Exc
  
!         def do(bad):
!             not bad
  
!         for func in (do, operator.not_):
!             self.assertRaises(Exc, func, Bad())
  
!     def test_recursion(self):
!         # Check comparison for recursive objects
!         from UserList import UserList
!         a = UserList(); a.append(a)
!         b = UserList(); b.append(b)
  
!         self.assert_(a == b)
!         self.assert_(not a != b)
!         a.append(1)
!         self.assert_(a == a[0])
!         self.assert_(not a != a[0])
!         self.assert_(a != b)
!         self.assert_(not a == b)
!         b.append(0)
!         self.assert_(a != b)
!         self.assert_(not a == b)
!         a[1] = -1
!         self.assert_(a != b)
!         self.assert_(not a == b)
  
!         a = UserList()
!         b = UserList()
!         a.append(b)
!         b.append(a)
!         self.assert_(a == b)
!         self.assert_(not a != b)
  
!         b.append(17)
!         self.assert_(a != b)
!         self.assert_(not a == b)
!         a.append(17)
!         self.assert_(a == b)
!         self.assert_(not a != b)
  
!     def test_recursion2(self):
!         # This test exercises the circular structure handling code
!         # in PyObject_RichCompare()
!         class Weird(object):
!             def __eq__(self, other):
!                 return self != other
!             def __ne__(self, other):
!                 return self == other
!             def __lt__(self, other):
!                 return self > other
!             def __gt__(self, other):
!                 return self < other
! 
!         self.assert_(Weird() == Weird())
!         self.assert_(not (Weird() != Weird()))
! 
!         for op in opmap["lt"]:
!             self.assertRaises(ValueError, op, Weird(), Weird())
! 
! class DictTest(unittest.TestCase):
! 
!     def test_dicts(self):
!         # Verify that __eq__ and __ne__ work for dicts even if the keys and
!         # values don't support anything other than __eq__ and __ne__.  Complex
!         # numbers are a fine example of that.
!         import random
!         imag1a = {}
!         for i in range(50):
!             imag1a[random.randrange(100)*1j] = random.randrange(100)*1j
!         items = imag1a.items()
!         random.shuffle(items)
!         imag1b = {}
!         for k, v in items:
!             imag1b[k] = v
!         imag2 = imag1b.copy()
!         imag2[k] = v + 1.0
!         self.assert_(imag1a == imag1a)
!         self.assert_(imag1a == imag1b)
!         self.assert_(imag2 == imag2)
!         self.assert_(imag1a != imag2)
!         for opname in ("lt", "le", "gt", "ge"):
!             for op in opmap[opname]:
!                 self.assertRaises(TypeError, op, imag1a, imag2)
! 
! class ListTest(unittest.TestCase):
! 
!     def assertIs(self, a, b):
!         self.assert_(a is b)
! 
!     def test_coverage(self):
!         # exercise all comparisons for lists
!         x = [42]
!         self.assertIs(x<x, False)
!         self.assertIs(x<=x, True)
!         self.assertIs(x==x, True)
!         self.assertIs(x!=x, False)
!         self.assertIs(x>x, False)
!         self.assertIs(x>=x, True)
!         y = [42, 42]
!         self.assertIs(x<y, True)
!         self.assertIs(x<=y, True)
!         self.assertIs(x==y, False)
!         self.assertIs(x!=y, True)
!         self.assertIs(x>y, False)
!         self.assertIs(x>=y, False)
! 
!     def test_badentry(self):
!         # make sure that exceptions for item comparison are properly
!         # propagated in list comparisons
!         class Exc:
              pass
!         class Bad:
!             def __eq__(self, other):
!                 raise Exc
  
!         x = [Bad()]
!         y = [Bad()]
  
!         for op in opmap["eq"]:
!             self.assertRaises(Exc, op, x, y)
! 
!     def test_goodentry(self):
!         # This test exercises the final call to PyObject_RichCompare()
!         # in Objects/listobject.c::list_richcompare()
!         class Good:
!             def __lt__(self, other):
!                 return True
! 
!         x = [Good()]
!         y = [Good()]
! 
!         for op in opmap["lt"]:
!             self.assertIs(op(x, y), True)
! 
! def test_main():
!     test_support.run_classtests(VectorTest, NumberTest, MiscTest, DictTest, ListTest)
! 
! if __name__ == "__main__":
!     test_main()