blob: 98d186f7aa4810f4a9343f370785555e9c89c9eb [file] [log] [blame]
Craig Harrisone3ea8f22012-10-01 13:55:21 -07001# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import threading
Craig Harrisonfc459df2012-10-04 13:49:48 -07006import time
Craig Harrisone3ea8f22012-10-01 13:55:21 -07007
8
Craig Harrisonfc459df2012-10-04 13:49:48 -07009class BaseStressor(threading.Thread):
10 """
11 Implements common functionality for *Stressor classes.
12
13 @var stressor: callable which performs a single stress event.
14 """
Craig Harrisone3ea8f22012-10-01 13:55:21 -070015 def __init__(self, stressor):
Craig Harrisone3ea8f22012-10-01 13:55:21 -070016 """
Craig Harrisonfc459df2012-10-04 13:49:48 -070017 Initialize the ControlledStressor.
18
19 @param stressor: callable which performs a single stress event.
20 """
21 super(BaseStressor, self).__init__()
Craig Harrisone3ea8f22012-10-01 13:55:21 -070022 self.daemon = True
Craig Harrisonfc459df2012-10-04 13:49:48 -070023 self.stressor = stressor
24
25
26 def start(self, start_condition=None):
27 """
28 Creates a new thread which will call the run() method.
29
30 Optionally takes a wait condition before the stressor loop. Returns
31 immediately.
32
33 @param start_condition: the new thread will wait to until this optional
34 callable returns True before running the stressor.
35 """
36 self._start_condition = start_condition
37 super(BaseStressor, self).start()
Craig Harrisone3ea8f22012-10-01 13:55:21 -070038
39
40 def run(self):
Craig Harrisonfc459df2012-10-04 13:49:48 -070041 """
42 Introduce a delay then start the stressor loop.
43
44 Overloaded from threading.Thread. This is run in a separate thread when
45 start() is called.
46 """
47 if self._start_condition:
48 while not self._start_condition():
49 time.sleep(1)
50 self._loop_stressor()
51
52
53 def _loop_stressor(self):
54 """
55 Apply stressor in a loop.
56
57 Overloaded by the particular *Stressor.
58 """
59 raise NotImplementedError
60
61
62class ControlledStressor(BaseStressor):
63 """
64 Run a stressor in loop on a separate thread.
65
66 Creates a new thread and calls |stressor| in a loop until stop() is called.
67 """
68 def __init__(self, stressor):
69 """
70 Initialize the ControlledStressor.
71
72 @param stressor: callable which performs a single stress event.
73 """
74 self._complete = threading.Event()
75 super(ControlledStressor, self).__init__(stressor)
76
77
78 def _loop_stressor(self):
79 """Overloaded from parent."""
Craig Harrisone3ea8f22012-10-01 13:55:21 -070080 while not self._complete.is_set():
Craig Harrisonfc459df2012-10-04 13:49:48 -070081 self.stressor()
Craig Harrisone3ea8f22012-10-01 13:55:21 -070082
83
Craig Harrisonfc459df2012-10-04 13:49:48 -070084 def start(self, start_condition=None):
85 """Start applying the stressor.
86
87 Overloaded from parent.
88
89 @param start_condition: the new thread will wait to until this optional
90 callable returns True before running the stressor.
91 """
Craig Harrisone3ea8f22012-10-01 13:55:21 -070092 self._complete.clear()
Craig Harrisonfc459df2012-10-04 13:49:48 -070093 super(ControlledStressor, self).start(start_condition)
Craig Harrisone3ea8f22012-10-01 13:55:21 -070094
95
96 def stop(self, timeout=45):
Craig Harrisonfc459df2012-10-04 13:49:48 -070097 """
98 Stop applying the stressor.
Craig Harrisone3ea8f22012-10-01 13:55:21 -070099
Craig Harrisonfc459df2012-10-04 13:49:48 -0700100 @param timeout: maximum time to wait for a single run of the stressor to
101 complete, defaults to 45 seconds.
102 """
Craig Harrisone3ea8f22012-10-01 13:55:21 -0700103 self._complete.set()
104 self.join(timeout)
105
106
Craig Harrisonfc459df2012-10-04 13:49:48 -0700107class CountedStressor(BaseStressor):
108 """
109 Run a stressor in a loop on a separate thread a given number of times.
Craig Harrisone3ea8f22012-10-01 13:55:21 -0700110
Craig Harrisonfc459df2012-10-04 13:49:48 -0700111 Creates a new thread and calls |stressor| in a loop |count| times. The
112 calling thread can use wait() to block until the loop completes.
113 """
114 def _loop_stressor(self):
115 """Overloaded from parent."""
Craig Harrisone3ea8f22012-10-01 13:55:21 -0700116 for i in xrange(self._count):
Craig Harrisonfc459df2012-10-04 13:49:48 -0700117 self.stressor()
Craig Harrisone3ea8f22012-10-01 13:55:21 -0700118
119
Craig Harrisonfc459df2012-10-04 13:49:48 -0700120 def start(self, count, start_condition=None):
121 """
122 Apply the stressor a given number of times.
Craig Harrisone3ea8f22012-10-01 13:55:21 -0700123
Craig Harrisonfc459df2012-10-04 13:49:48 -0700124 Overloaded from parent.
125
126 @param count: number of times to apply the stressor.
127 @param start_condition: the new thread will wait to until this optional
128 callable returns True before running the stressor.
Craig Harrisone3ea8f22012-10-01 13:55:21 -0700129 """
130 self._count = count
Craig Harrisonfc459df2012-10-04 13:49:48 -0700131 super(CountedStressor, self).start(start_condition)
Craig Harrisone3ea8f22012-10-01 13:55:21 -0700132
133
134 def wait(self, timeout=None):
135 """Wait until the stressor completes.
136
Craig Harrisonfc459df2012-10-04 13:49:48 -0700137 @param timeout: maximum time for the thread to complete, by default
138 never times out.
Craig Harrisone3ea8f22012-10-01 13:55:21 -0700139 """
140 self.join(timeout)