[pypy-svn] r60867 - pypy/trunk/pypy/objspace/test

pedronis at codespeak.net pedronis at codespeak.net
Sat Jan 10 13:37:19 CET 2009


Author: pedronis
Date: Sat Jan 10 13:37:17 2009
New Revision: 60867

Added:
   pypy/trunk/pypy/objspace/test/test_binop_overriding.py   (contents, props changed)
Log:
issue412 in-progress

tests about issue412, they pass on cpython but fails on PyPy, made most of them run only with py.test -A because they are quite exhaistive but slow



Added: pypy/trunk/pypy/objspace/test/test_binop_overriding.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/objspace/test/test_binop_overriding.py	Sat Jan 10 13:37:17 2009
@@ -0,0 +1,175 @@
+# test about the binop operation rule, see issue 412
+from pypy.conftest import option
+
+class AppTestBinopCombinations:
+
+    def setup_class(cls):
+        w_helpers = cls.space.appexec([], """():
+    class Base(object):
+        def __init__(self, name):
+            self.name = name
+
+    def lookup_where(obj, name):
+        mro = type(obj).__mro__
+        for t in mro:
+            if name in t.__dict__:
+                return t.__dict__[name], t
+        return None, None
+
+    def refop(x, y, opname, ropname):
+        # this has been validated by running the tests on top of cpython
+        # so for the space of possibilities that the tests touch it is known
+        # to behave like cpython as long as the latter doesn't change its own
+        # algorithm
+        t1 = type(x)
+        t2 = type(y)
+        op, where1 = lookup_where(x, opname)
+        rop, where2 = lookup_where(y, ropname)
+        if op is None and rop is not None:
+            return rop(y, x)
+        if rop and where1 is not where2:
+            if (issubclass(t2, t1) and not issubclass(where1, where2)
+                and not issubclass(t1, where2)
+                ):
+                return rop(y, x)
+        if op is None:
+            return "TypeError"
+        return op(x,y)
+
+    def do_test(X, Y, name, impl):
+        x = X('x')
+        y = Y('y')
+        opname = '__%s__' % name
+        ropname = '__r%s__' % name
+
+        count = [0]
+        fail = []
+
+        def check(z1, z2):
+            ref = refop(z1, z2, opname, ropname)
+            try:
+                v = impl(z1, z2)
+            except TypeError:
+                v = "TypeError"
+            if v != ref:
+                fail.append(count[0])
+
+        def override_in_hier(n=6):
+            if n == 0:
+                count[0] += 1
+                check(x, y)
+                check(y, x)
+                return
+
+            f = lambda self, other: (n, self.name, other.name)
+            if n%2 == 0:
+                name = opname
+            else:
+                name = ropname
+
+            for C in Y.__mro__:
+                if name in C.__dict__:
+                    continue
+                if C is not object:
+                    setattr(C, name, f)
+                override_in_hier(n-1)
+                if C is not object:        
+                    delattr(C, name)
+
+        override_in_hier()
+        #print count[0]
+        return fail
+
+    return Base, do_test
+""")
+        cls.w_helpers = w_helpers
+        cls.w_appdirect = cls.space.wrap(option.runappdirect)
+
+    def test_overriding_base_binop_explict(self):
+        if not self.appdirect:        
+            skip("fails, issue412")
+        class MulBase(object):
+            def __init__(self, value):
+                self.value = value
+            def __mul__(self, other):
+                return self.value * other.value
+            def __rmul__(self, other):
+                return other.value * self.value
+        class DoublerBase(MulBase):
+            def __mul__(self, other):
+                return 2 * (self.value * other.value)
+        class AnotherDoubler(DoublerBase):
+            pass
+        res = DoublerBase(2) * AnotherDoubler(3)
+        assert res == 12
+
+    def test_binop_combinations_mul(self):
+        if not self.appdirect:
+            skip("slow test, should be run as appdirect test")
+        Base, do_test = self.helpers
+         
+        class X(Base):
+            pass
+        class Y(X):
+            pass
+
+        fail = do_test(X, Y, 'mul', lambda x,y: x*y)
+        #print len(fail)
+        assert not fail
+
+    def test_binop_combinations_sub(self):
+        if not self.appdirect:        
+            skip("fails, issue412")
+        Base, do_test = self.helpers        
+        class X(Base):
+            pass
+        class Y(X):
+            pass
+
+        fail = do_test(X, Y, 'sub', lambda x,y: x-y)
+        #print len(fail)
+        assert not fail        
+
+    def test_binop_combinations_pow(self):
+        if not self.appdirect:
+            skip("slow test, should be run as appdirect test")
+        Base, do_test = self.helpers
+        
+        class X(Base):
+            pass
+        class Y(X):
+            pass
+
+        fail = do_test(X, Y, 'pow', lambda x,y: x**y)
+        #print len(fail)
+        assert not fail        
+
+    def test_binop_combinations_more_exhaustive(self):
+        if not self.appdirect:
+            skip("very slow test, should be run as appdirect test")
+        Base, do_test = self.helpers
+        
+        class X(Base):
+            pass
+
+        class B1(object):
+            pass
+
+        class B2(object):
+            pass
+
+        class X1(B1, X, B2):
+            pass
+
+        class C1(object):
+            pass
+
+        class C2(object):
+            pass
+
+        class Y(C1, X1, C2):
+            pass
+
+        fail = do_test(X, Y, 'sub', lambda x,y: x-y)
+        #print len(fail)
+        assert not fail



More information about the Pypy-commit mailing list