diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -50,6 +50,7 @@ import time import traceback import distutils.spawn +import contextlib # Third-party modules import unittest2 @@ -1850,6 +1851,285 @@ # Can be overridden by the LLDB_TIME_WAIT_NEXT_LAUNCH environment variable. timeWaitNextLaunch = 1.0 + def enter_batch(self): + self._batch = True + + def exit_batch(self): + self._batch = False + + @contextlib.contextmanager + def batchTest(self): + try: + self.enter_batch() + yield + finally: + self.exit_batch() + + # Assertion Overides + def assertTrue(self, expr, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertTrue(expr, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertTrue(expr, msg) + + def assertFalse(self, expr, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertFalse( expr, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertFalse( expr, msg) + def assertRaises(self,excClass, callableObj=None, *args, **kwargs): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertRaises(excClass, callableObj, *args, **kwargs) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertRaises(excClass, callableObj, *args, **kwargs) + def assertEqual(self, first, second, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertEqual( first, second, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertEqual( first, second, msg) + def assertNotEqual(self, first, second, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertNotEqual( first, second, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertNotEqual( first, second, msg) + def assertAlmostEqual(self, first, second, places=None, msg=None, delta=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertAlmostEqual( first, second, places, msg, delta) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertAlmostEqual( first, second, places, msg, delta) + def assertNotAlmostEqual(self, first, second, places=None, msg=None, delta=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertNotAlmostEqual( first, second, places, msg, delta) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertNotAlmostEqual( first, second, places, msg, delta) + # assertSequenceEqual is called internally by the following methods, so overriding it may obscure traceback during failures + def assertListEqual(self, list1, list2, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertListEqual( list1, list2, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertListEqual( list1, list2, msg) + def assertTupleEqual(self, tuple1, tuple2, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertTupleEqual( tuple1, tuple2, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertTupleEqual( tuple1, tuple2, msg) + def assertSetEqual(self, set1, set2, msg=None): + if self._result is not None and self._batch: + try: + super(TestBase,self).assertSetEqual( set1, set2, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + super(TestBase,self).assertSetEqual( set1, set2, msg) + def assertIn(self, member, container, msg=None): + if self._result is not None and self._batch: + try: + super(TestBase,self).assertIn( member, container, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + super(TestBase,self).assertIn( member, container, msg) + def assertNotIn(self, member, container, msg=None): + if self._result is not None and self._batch: + try: + super(TestBase,self).assertNotIn( member, container, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + super(TestBase,self).assertNotIn( member, container, msg) + def assertIs(self, expr1, expr2, msg=None): + if self._result is not None and self._batch: + try: + super(TestBase,self).assertIs( expr1, expr2, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + super(TestBase,self).assertIs( expr1, expr2, msg) + def assertIsNot(self, expr1, expr2, msg=None): + if self._result is not None and self._batch: + try: + super(TestBase,self).assertIsNot( expr1, expr2, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + super(TestBase,self).assertIsNot( expr1, expr2, msg) + def assertDictEqual(self, d1, d2, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertDictEqual( d1, d2, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertDictEqual( d1, d2, msg) + def assertDictContainsSubset(self, expected, actual, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertDictContainsSubset( expected, actual, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertDictContainsSubset( expected, actual, msg) + def assertItemsEqual(self, expected_seq, actual_seq, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertItemsEqual( expected_seq, actual_seq, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertItemsEqual( expected_seq, actual_seq, msg) + def assertMultiLineEqual(self, first, second, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertMultiLineEqual( first, second, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertMultiLineEqual( first, second, msg) + def assertLess(self, a, b, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertLess( a, b, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertLess( a, b, msg) + def assertLessEqual(self, a, b, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertLessEqual( a, b, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertLessEqual( a, b, msg) + def assertGreater(self, a, b, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertGreater( a, b, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertGreater( a, b, msg) + def assertGreaterEqual(self, a, b, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertGreaterEqual( a, b, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertGreaterEqual( a, b, msg) + def assertIsNone(self, obj, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertIsNone( obj, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertIsNone( obj, msg) + def assertIsNotNone(self, obj, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertIsNotNone( obj, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertIsNotNone( obj, msg) + def assertIsInstance(self, obj, cls, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertIsInstance( obj, cls, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertIsInstance( obj, cls, msg) + def assertNotIsInstance(self, obj, cls, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertNotIsInstance( obj, cls, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertNotIsInstance( obj, cls, msg) + def assertRaisesRegexp(self, expected_exception, expected_regexp, callable_obj=None, *args, **kwargs): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertRaisesRegexp( expected_exception, expected_regexp, callable_obj, *args, **kwargs) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertRaisesRegexp( expected_exception, expected_regexp, callable_obj, *args, **kwargs) + def assertRegexpMatches(self, text, expected_regexp, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertRegexpMatches( text, expected_regexp, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertRegexpMatches( text, expected_regexp, msg) + def assertNotRegexpMatches(self, text, unexpected_regexp, msg=None): + if self._result is not None and self._batch: + try: + return super(TestBase,self).assertNotRegexpMatches( text, unexpected_regexp, msg) + except self.failureException: + self._result.addFailure(self, sys.exc_info()) + self._batchSuccess = False + else: + return super(TestBase,self).assertNotRegexpMatches( text, unexpected_regexp, msg) + def generateSource(self, source): template = source + '.template' temp = os.path.join(self.getSourceDir(), template) diff --git a/lldb/test/API/test_batch/TestBatch.py b/lldb/test/API/test_batch/TestBatch.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/test_batch/TestBatch.py @@ -0,0 +1,31 @@ +from lldbsuite.test.lldbtest import * + +class TestBatch(TestBase): + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + x = 0 + + def test_batch(self): + self.enter_batch() + + self.assertTrue(False) + self.assertTrue(False) + + self.assertTrue(True) + + self.exit_batch() + + def test_context_manager(self): + with self.batchTest(): + self.x += 1 + self.assertFalse(True) + self.assertFalse(True) + self.assertEqual(self.x, 1) + + def test_early_exit(self): + with self.batchTest(): + self.assertFalse(True) + self.assertFalse(False) + raise IndexError + self.assertTrue(False) diff --git a/lldb/third_party/Python/module/unittest2/unittest2/case.py b/lldb/third_party/Python/module/unittest2/unittest2/case.py --- a/lldb/third_party/Python/module/unittest2/unittest2/case.py +++ b/lldb/third_party/Python/module/unittest2/unittest2/case.py @@ -234,6 +234,10 @@ """ self._testMethodName = methodName self._resultForDoCleanups = None + + self._batch = False + self._result = None + try: testMethod = getattr(self, methodName) except AttributeError: @@ -410,6 +414,8 @@ SB objects and prevent them from being deleted in time. """ try: + self._result = result + self._result.batchSuccess = True # Just in case testMethod() except self.failureException: result.addFailure(self, sys.exc_info()) @@ -437,7 +443,8 @@ except Exception: result.addError(self, sys.exc_info()) else: - return True + return self._result.batchSuccess + self._result = None return False def doCleanups(self): diff --git a/lldb/third_party/Python/module/unittest2/unittest2/result.py b/lldb/third_party/Python/module/unittest2/unittest2/result.py --- a/lldb/third_party/Python/module/unittest2/unittest2/result.py +++ b/lldb/third_party/Python/module/unittest2/unittest2/result.py @@ -58,6 +58,7 @@ self._original_stdout = sys.stdout self._original_stderr = sys.stderr self._mirrorOutput = False + self.batchSuccess = True def startTest(self, test): "Called when the given test is about to be run"