OILS / opy / byterun / vmtest.py View on Github | oilshell.org

98 lines, 63 significant
1"""Testing tools for byterun."""
2
3from __future__ import print_function
4
5import cStringIO
6import sys
7import textwrap
8import types
9import unittest
10
11
12from opy.lib import dis
13import pyvm2
14
15# Make this false if you need to run the debugger inside a test.
16CAPTURE_STDOUT = ('-s' not in sys.argv)
17# Make this false to see the traceback from a failure inside pyvm2.
18CAPTURE_EXCEPTION = 1
19
20
21def dis_code(code):
22 """Disassemble `code` and all the code it refers to."""
23 return
24 for const in code.co_consts:
25 if isinstance(const, types.CodeType):
26 dis_code(const)
27
28 print("")
29 print(code)
30 dis.dis(code)
31
32
33class VmTestCase(unittest.TestCase):
34
35 def assert_ok(self, code, raises=None):
36 """Run `code` in our VM and in real Python: they behave the same."""
37
38 code = textwrap.dedent(code)
39 code = compile(code, "<%s>" % self.id(), "exec", 0, 1)
40
41 # Print the disassembly so we'll see it if the test fails.
42 dis_code(code)
43
44 real_stdout = sys.stdout
45
46 # Run the code through our VM.
47
48 vm_stdout = cStringIO.StringIO()
49 if CAPTURE_STDOUT: # pragma: no branch
50 sys.stdout = vm_stdout
51 vm = pyvm2.VirtualMachine()
52
53 vm_value = vm_exc = None
54 try:
55 vm_value = pyvm2.run_code(vm, code)
56 except pyvm2.VirtualMachineError: # pragma: no cover
57 # If the VM code raises an error, show it.
58 raise
59 except AssertionError: # pragma: no cover
60 # If test code fails an assert, show it.
61 raise
62 except Exception as e:
63 # Otherwise, keep the exception for comparison later.
64 if not CAPTURE_EXCEPTION: # pragma: no cover
65 raise
66 vm_exc = e
67 finally:
68 real_stdout.write("-- stdout ----------\n")
69 real_stdout.write(vm_stdout.getvalue())
70
71 # Run the code through the real Python interpreter, for comparison.
72
73 py_stdout = cStringIO.StringIO()
74 sys.stdout = py_stdout
75
76 py_value = py_exc = None
77 globs = {}
78 try:
79 py_value = eval(code, globs, globs)
80 except AssertionError: # pragma: no cover
81 raise
82 except Exception as e:
83 py_exc = e
84
85 sys.stdout = real_stdout
86
87 self.assert_same_exception(vm_exc, py_exc)
88 self.assertEqual(vm_stdout.getvalue(), py_stdout.getvalue())
89 self.assertEqual(vm_value, py_value)
90 if raises:
91 self.assertIsInstance(vm_exc, raises)
92 else:
93 self.assertIsNone(vm_exc)
94
95 def assert_same_exception(self, e1, e2):
96 """Exceptions don't implement __eq__, check it ourselves."""
97 self.assertEqual(str(e1), str(e2))
98 self.assertIs(type(e1), type(e2))