~ihanick/percona-server/5.1.59-innodb_log_archiving

« back to all changes in this revision

Viewing changes to python-for-subunit2junitxml/testtools/testsuite.py

  • Committer: Stewart Smith
  • Date: 2011-10-06 06:45:16 UTC
  • Revision ID: stewart@flamingspork.com-20111006064516-rrjg17x7wwn9vr6w
add subunit support to mtr

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2009 testtools developers. See LICENSE for details.
 
2
 
 
3
"""Test suites and related things."""
 
4
 
 
5
__metaclass__ = type
 
6
__all__ = [
 
7
  'ConcurrentTestSuite',
 
8
  'iterate_tests',
 
9
  ]
 
10
 
 
11
try:
 
12
    from Queue import Queue
 
13
except ImportError:
 
14
    from queue import Queue
 
15
import threading
 
16
import unittest
 
17
 
 
18
import testtools
 
19
 
 
20
 
 
21
def iterate_tests(test_suite_or_case):
 
22
    """Iterate through all of the test cases in 'test_suite_or_case'."""
 
23
    try:
 
24
        suite = iter(test_suite_or_case)
 
25
    except TypeError:
 
26
        yield test_suite_or_case
 
27
    else:
 
28
        for test in suite:
 
29
            for subtest in iterate_tests(test):
 
30
                yield subtest
 
31
 
 
32
 
 
33
class ConcurrentTestSuite(unittest.TestSuite):
 
34
    """A TestSuite whose run() calls out to a concurrency strategy."""
 
35
 
 
36
    def __init__(self, suite, make_tests):
 
37
        """Create a ConcurrentTestSuite to execute suite.
 
38
 
 
39
        :param suite: A suite to run concurrently.
 
40
        :param make_tests: A helper function to split the tests in the
 
41
            ConcurrentTestSuite into some number of concurrently executing
 
42
            sub-suites. make_tests must take a suite, and return an iterable
 
43
            of TestCase-like object, each of which must have a run(result)
 
44
            method.
 
45
        """
 
46
        super(ConcurrentTestSuite, self).__init__([suite])
 
47
        self.make_tests = make_tests
 
48
 
 
49
    def run(self, result):
 
50
        """Run the tests concurrently.
 
51
 
 
52
        This calls out to the provided make_tests helper, and then serialises
 
53
        the results so that result only sees activity from one TestCase at
 
54
        a time.
 
55
 
 
56
        ConcurrentTestSuite provides no special mechanism to stop the tests
 
57
        returned by make_tests, it is up to the make_tests to honour the
 
58
        shouldStop attribute on the result object they are run with, which will
 
59
        be set if an exception is raised in the thread which
 
60
        ConcurrentTestSuite.run is called in.
 
61
        """
 
62
        tests = self.make_tests(self)
 
63
        try:
 
64
            threads = {}
 
65
            queue = Queue()
 
66
            result_semaphore = threading.Semaphore(1)
 
67
            for test in tests:
 
68
                process_result = testtools.ThreadsafeForwardingResult(result,
 
69
                    result_semaphore)
 
70
                reader_thread = threading.Thread(
 
71
                    target=self._run_test, args=(test, process_result, queue))
 
72
                threads[test] = reader_thread, process_result
 
73
                reader_thread.start()
 
74
            while threads:
 
75
                finished_test = queue.get()
 
76
                threads[finished_test][0].join()
 
77
                del threads[finished_test]
 
78
        except:
 
79
            for thread, process_result in threads.values():
 
80
                process_result.stop()
 
81
            raise
 
82
 
 
83
    def _run_test(self, test, process_result, queue):
 
84
        try:
 
85
            test.run(process_result)
 
86
        finally:
 
87
            queue.put(test)