Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: testing_support/thread_watcher.py

Issue 2127943002: Thread Watcher: don't fail when test already failed. (Closed) Base URL: https://chromium.googlesource.com/infra/testing/testing_support.git@master
Patch Set: review Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « testing_support/tests/thread_watcher_test.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2016 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 5
6 import logging
6 import sys 7 import sys
7 import threading 8 import threading
8 import traceback 9 import traceback
9 import unittest 10 import unittest
10 11
11 12
12 class ThreadWatcherMixIn(object): 13 class ThreadWatcherMixIn(object):
13 def setUp(self): 14 def setUp(self):
14 self._pre_test_threads = [t.ident for t in threading.enumerate()] 15 self._pre_test_threads = [t.ident for t in threading.enumerate()]
15 16
16 def tearDown(self): 17 def tearDown(self):
18 # If test failed before this check, don't raise another exception
19 # overwriting the original one, and making it harder to debug.
20 # Besides, that exception might be the reason cleanup didn't happen.
21 if self._test_definitely_failed():
22 return
23
17 post_test_threads = threading.enumerate() 24 post_test_threads = threading.enumerate()
18 new_threads = [t for t in post_test_threads 25 new_threads = [t for t in post_test_threads
19 if t.ident not in self._pre_test_threads] 26 if t.ident not in self._pre_test_threads]
20 if new_threads: 27 if new_threads:
21 details = [] 28 details = []
22 for th in new_threads: 29 for th in new_threads:
23 details.append('\nThread %s stacktrace:\n' % th) 30 details.append('\nThread %s stacktrace:\n' % th)
24 try: 31 try:
25 details.extend(traceback.format_stack(sys._current_frames()[t.ident])) 32 details.extend(traceback.format_stack(sys._current_frames()[t.ident]))
26 except Exception: 33 except Exception:
27 if t.ident in sys._current_frames(): 34 if t.ident in sys._current_frames():
28 raise 35 raise
29 # This can happen due to threads starting or stopping concurrently. 36 # This can happen due to threads starting or stopping concurrently.
30 details.append(' Thread stopped while acquiring stacktrace.\n') 37 details.append(' Thread stopped while acquiring stacktrace.\n')
31 details = ''.join(details) 38 details = ''.join(details)
32 39
33 self.fail('Found %d running thread(s) after the test.\n%s' % ( 40 self.fail('Found %d running thread(s) after the test.\n%s' % (
34 len(new_threads), details)) 41 len(new_threads), details))
35 42
43 def _test_definitely_failed(self):
44 """Returns True only if test has definitely failed already.
45
46 This is necessary to determine whether we should fail the test when finding
47 stray threads. If the test has failed in some other way, we should avoid
48 throwing an exception because it will mask the original error.
49 """
50 # When run using unittest runner,
51 # self._resultForDoCleanups is set to internal unittest object.
52 if hasattr(self, '_resultForDoCleanups') and self._resultForDoCleanups:
53 return not self._resultForDoCleanups.wasSuccessful()
54 # expect_tests runner does so differently (see
55 # https://codereview.chromium.org/2121343004).
56 if hasattr(self, '_test_failed_with_exception'):
57 return self._test_failed_with_exception
58 # Default case - be conservative.
59 return False
36 60
37 61
38 class TestCase(unittest.TestCase, ThreadWatcherMixIn): 62 class TestCase(unittest.TestCase, ThreadWatcherMixIn):
39 """Base unittest class that fails on leaked threads after the test.""" 63 """Base unittest class that fails on leaked threads after the test."""
40 def setUp(self): 64 def setUp(self):
41 super(TestCase, self).setUp() 65 super(TestCase, self).setUp()
42 ThreadWatcherMixIn.setUp(self) 66 ThreadWatcherMixIn.setUp(self)
43 67
44 def tearDown(self): 68 def tearDown(self):
45 ThreadWatcherMixIn.tearDown(self) 69 ThreadWatcherMixIn.tearDown(self)
46 super(TestCase, self).tearDown() 70 super(TestCase, self).tearDown()
OLDNEW
« no previous file with comments | « testing_support/tests/thread_watcher_test.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698