[pypy-svn] pypy default: try to print relevant information when the loop does not match

antocuni commits-noreply at bitbucket.org
Mon Mar 14 14:55:47 CET 2011


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: 
Changeset: r42607:09dbc4efa036
Date: 2011-03-14 14:45 +0100
http://bitbucket.org/pypy/pypy/changeset/09dbc4efa036/

Log:	try to print relevant information when the loop does not match

diff --git a/pypy/module/pypyjit/test_pypy_c/model.py b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -1,4 +1,5 @@
 import py
+import sys
 import re
 import os.path
 from pypy.tool.jitlogparser.parser import SimpleParser, Function, TraceForOpcode
@@ -132,12 +133,15 @@
             for op in self._ops_for_chunk(chunk, include_debug_merge_points):
                 yield op
 
-    def print_ops(self, id=None, **kwds):
+    def format_ops(self, id=None, **kwds):
         if id is None:
             ops = self.allops()
         else:
             ops = self.ops_by_id(id, **kwds)
-        print '\n'.join(map(str, ops))
+        return '\n'.join(map(str, ops))
+
+    def print_ops(self, *args, **kwds):
+        print self.format_ops(*args, **kwds)
 
     def ops_by_id(self, id, include_debug_merge_points=False, opcode=None):
         opcode_name = opcode
@@ -151,7 +155,7 @@
 
     def match(self, expected_src):
         ops = list(self.allops())
-        matcher = OpMatcher(ops)
+        matcher = OpMatcher(ops, src=self.format_ops())
         return matcher.match(expected_src)
 
     def match_by_id(self, id, expected_src):
@@ -160,12 +164,36 @@
         return matcher.match(expected_src)
 
 class InvalidMatch(Exception):
-    pass
+
+    def __init__(self, message, frame):
+        Exception.__init__(self, message)
+        # copied and adapted from pytest's magic AssertionError
+        f = py.code.Frame(frame)
+        try:
+            source = f.code.fullsource
+            if source is not None:
+                try:
+                    source = source.getstatement(f.lineno)
+                except IndexError:
+                    source = None
+                else:
+                    source = str(source.deindent()).strip()
+        except py.error.ENOENT:
+            source = None
+        if source and source.startswith('self._assert('):
+            # transform self._assert(x, 'foo') into assert x, 'foo'
+            source = source.replace('self._assert(', 'assert ')
+            source = source[:-1] # remove the trailing ')'
+            self.msg = py.code._reinterpret(source, f, should_fail=True)
+        else:
+            self.msg = "<could not determine information>"
+
 
 class OpMatcher(object):
 
-    def __init__(self, ops):
+    def __init__(self, ops, src=None):
         self.ops = ops
+        self.src = src
         self.alpha_map = {}
 
     @classmethod
@@ -195,9 +223,7 @@
         args = args[:-1]
         args = args.split(',')
         args = map(str.strip, args)
-        if args == ['']:
-            args = []
-        if args and args[-1].startswith('descr='):
+        if args[-1].startswith('descr='):
             descr = args.pop()
             descr = descr[len('descr='):]
         else:
@@ -236,7 +262,7 @@
 
     def _assert(self, cond, message):
         if not cond:
-            raise InvalidMatch(message)
+            raise InvalidMatch(message, frame=sys._getframe(1))
 
     def match_op(self, op, (exp_opname, exp_res, exp_args, exp_descr)):
         self._assert(op.name == exp_opname, "operation mismatch")
@@ -302,8 +328,18 @@
         expected_ops = self.parse_ops(expected_src)
         try:
             self.match_loop(expected_ops)
-        except InvalidMatch:
+        except InvalidMatch, e:
             #raise # uncomment this and use py.test --pdb for better debugging
+            print '@' * 40
+            print "Loops don't match"
+            print "================="
+            print e.msg
+            print
+            print "Got:"
+            print py.code.Source(self.src).deindent().indent()
+            print
+            print "Expected:"
+            print py.code.Source(expected_src).deindent().indent()
             return False
         else:
             return True

diff --git a/pypy/module/pypyjit/test_pypy_c/test_model.py b/pypy/module/pypyjit/test_pypy_c/test_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_model.py
@@ -98,7 +98,7 @@
     def match(self, src1, src2):
         from pypy.tool.jitlogparser.parser import SimpleParser
         loop = SimpleParser.parse_from_input(src1)
-        matcher = OpMatcher(loop.operations)
+        matcher = OpMatcher(loop.operations, src=src1)
         return matcher.match(src2)
 
     def test_match_var(self):


More information about the Pypy-commit mailing list