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

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: Test. 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
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):
Michael Achenbach 2016/07/07 12:30:41 Can setUp be called concurrently?
tandrii(chromium) 2016/07/07 12:56:39 nope, at least not in the same thread on the same
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 not self._test_likely_passed():
Michael Achenbach 2016/07/07 12:30:41 readability nit: Maybe negate the logic in the met
tandrii(chromium) 2016/07/07 12:56:39 Good idea! Done.
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_likely_passed(self):
Michael Achenbach 2016/07/07 12:30:41 I'm not so happy about the method name. Doesn't lo
tandrii(chromium) 2016/07/07 12:56:39 That's fair. I've renamed it.
44 """Conservatively returns True if current test has likely not failed yet.
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 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 not self._test_failed_with_exception
58 # Default case - be conservative.
59 return True
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
« testing_support/tests/thread_watcher_test.py ('K') | « 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