• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hivesolutions / colony / 877

pending completion
877

push

travis-ci-com

joamag
test: refactored scheduling tests making re-use of scheduler

Also added a timeout overflow handling strategy

87 of 87 new or added lines in 3 files covered. (100.0%)

3274 of 6589 relevant lines covered (49.69%)

2.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.68
/src/colony/test/libs/scheduling_util.py
1
#!/usr/bin/python
2
# -*- coding: utf-8 -*-
3

4
# Hive Colony Framework
5
# Copyright (c) 2008-2020 Hive Solutions Lda.
6
#
7
# This file is part of Hive Colony Framework
8
#
9
# Hive Colony Framework is free software: you can redistribute it and/or modify
10
# it under the terms of the Apache License as published by the Apache
11
# Foundation, either version 2.0 of the License, or (at your option) any
12
# later version.
13
#
14
# Hive Colony Framework is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
# Apache License for more details.
18
#
19
# You should have received a copy of the Apache License along with
20
# Hive Colony Framework If not, see <http://www.apache.org/licenses/>.
21

22
__author__ = "João Magalhães <joamag@hive.pt>"
5✔
23
""" The author(s) of the module """
24

25
__version__ = "1.0.0"
5✔
26
""" The version of the module """
27

28
__revision__ = "$LastChangedRevision$"
5✔
29
""" The revision number of the module """
30

31
__date__ = "$LastChangedDate$"
5✔
32
""" The last change date of the module """
33

34
__copyright__ = "Copyright (c) 2008-2020 Hive Solutions Lda."
5✔
35
""" The copyright for the module """
36

37
__license__ = "Apache License, Version 2.0"
5✔
38
""" The license for the module """
39

40
import time
5✔
41

42
import colony
5✔
43

44
class SchedulerTest(colony.ColonyTestCase):
5✔
45
    """
46
    Class that tests the scheduler up to the expected
47
    values, making sure that race and other weird conditions
48
    are properly handled.
49
    """
50

51
    def setUp(self):
5✔
52
        self.scheduler = colony.Scheduler()
5✔
53
        self.scheduler.start_scheduler()
5✔
54

55
    def tearDown(self):
5✔
56
        self.scheduler.stop_scheduler()
5✔
57
        self.scheduler.join(10)
5✔
58

59
    def test_basic(self):
5✔
60
        """
61
        Runs a series of basic sanity tests for the scheduler.
62
        """
63

64
        self.assertEqual(self.scheduler.is_running(), True)
5✔
65

66
        values = dict()
5✔
67

68
        def update_values():
5✔
69
            values["a"] = 1
5✔
70

71
        self.assertEqual(values, dict())
5✔
72

73
        identifier = self.scheduler.add_callable(update_values)
5✔
74
        self.scheduler.wait_callable(identifier)
5✔
75
        self.assertEqual(identifier, 1)
5✔
76
        self.assertEqual(values, dict(a = 1))
5✔
77
        self.assertEqual(self.scheduler.is_running(), True)
5✔
78
        self.assertEqual(self.scheduler.is_busy(), False)
5✔
79

80
        self.scheduler.reset_scheduler()
5✔
81
        self.assertEqual(self.scheduler.is_running(), False)
5✔
82
        self.assertEqual(self.scheduler.is_busy(), False)
5✔
83

84
    def test_delayed(self):
5✔
85
        """
86
        Tests that a delayed work can be scheduled and executed
87
        in the proper time.
88
        """
89

90
        self.assertEqual(self.scheduler.is_running(), True)
5✔
91

92
        values = dict()
5✔
93

94
        def update_values():
5✔
95
            values["a"] = 1
5✔
96

97
        self.assertEqual(values, dict())
5✔
98

99
        initial = time.time()
5✔
100
        identifier = self.scheduler.add_callable(update_values, timestamp = time.time() + 0.3)
5✔
101
        self.assertEqual(identifier, 1)
5✔
102
        time.sleep(0.1)
5✔
103
        self.assertEqual(values, dict())
5✔
104

105
        self.scheduler.wait_callable(identifier)
5✔
106
        self.assertEqual(time.time() - initial >= 0.3, True)
5✔
107
        self.assertEqual(values, dict(a = 1))
5✔
108

109
    def test_multiple(self):
5✔
110
        """
111
        Tests that multiple parallel callable tasks can be
112
        scheduled and executed.
113
        """
114

115
        self.assertEqual(self.scheduler.is_running(), True)
5✔
116

117
        values = dict()
5✔
118

119
        def update_values_1():
5✔
120
            values["a"] = 1
5✔
121

122
        def update_values_2():
5✔
123
            values["b"] = 2
5✔
124

125
        self.assertEqual(values, dict())
5✔
126

127
        identifier_1 = self.scheduler.add_callable(update_values_1)
5✔
128
        identifier_2 = self.scheduler.add_callable(update_values_2)
5✔
129
        self.scheduler.wait_callable(identifier_1)
5✔
130
        self.scheduler.wait_callable(identifier_2)
5✔
131
        self.assertEqual(identifier_1, 1)
5✔
132
        self.assertEqual(identifier_2, 2)
5✔
133
        self.assertEqual(values, dict(a = 1, b = 2))
5✔
134
        self.assertEqual(self.scheduler.is_running(), True)
5✔
135
        self.assertEqual(self.scheduler.is_busy(), False)
5✔
136

137
        values = dict()
5✔
138

139
        def update_values_3():
5✔
140
            values["a"] = 1
5✔
141

142
        def update_values_4():
5✔
143
            values["b"] = values["a"] + 1
5✔
144

145
        self.assertEqual(values, dict())
5✔
146

147
        identifier_1 = self.scheduler.add_callable(update_values_3, timestamp = time.time() + 0.1)
5✔
148
        identifier_2 = self.scheduler.add_callable(update_values_4, timestamp = time.time() + 0.2)
5✔
149
        self.scheduler.wait_callable(identifier_1)
5✔
150
        self.scheduler.wait_callable(identifier_2)
5✔
151
        self.assertEqual(identifier_1, 3)
5✔
152
        self.assertEqual(identifier_2, 4)
5✔
153
        self.assertEqual(values, dict(a = 1, b = 2))
5✔
154
        self.assertEqual(self.scheduler.is_running(), True)
5✔
155
        self.assertEqual(self.scheduler.is_busy(), False)
5✔
156

157
        values = dict()
5✔
158

159
        def update_values_5():
5✔
160
            values["a"] = values["b"] + 1
5✔
161

162
        def update_values_6():
5✔
163
            values["b"] = 2
5✔
164

165
        self.assertEqual(values, dict())
5✔
166

167
        identifier_1 = self.scheduler.add_callable(update_values_5, timestamp = time.time() + 0.2)
5✔
168
        identifier_2 = self.scheduler.add_callable(update_values_6, timestamp = time.time() + 0.1)
5✔
169
        self.scheduler.wait_callable(identifier_1)
5✔
170
        self.scheduler.wait_callable(identifier_2)
5✔
171
        self.assertEqual(identifier_1, 5)
5✔
172
        self.assertEqual(identifier_2, 6)
5✔
173
        self.assertEqual(values, dict(a = 3, b = 2))
5✔
174
        self.assertEqual(self.scheduler.is_running(), True)
5✔
175
        self.assertEqual(self.scheduler.is_busy(), False)
5✔
176

177
    def test_overflow(self):
5✔
178
        """
179
        Tests that it is possible to add a task that overflows
180
        the max timeout value for the scheduler.
181
        """
182

183
        self.assertEqual(self.scheduler.is_running(), True)
5✔
184

185
        values = dict()
5✔
186

187
        def update_values():
5✔
188
            values["a"] = 1
×
189

190
        self.assertEqual(values, dict())
5✔
191

192
        identifier = self.scheduler.add_callable(
5✔
193
            update_values,
194
            timestamp = time.time() + colony.SCHEDULING_MAX + 1
195
        )
196
        self.assertEqual(identifier, 1)
5✔
197
        self.assertEqual(self.scheduler.is_running(), True)
5✔
198

199
    def test_stopped(self):
5✔
200
        """
201
        Tests that if the scheduler is currently stopped then
202
        a series of consequences must happen.
203
        """
204

205
        self.assertEqual(self.scheduler.is_running(), True)
5✔
206

207
        self.scheduler.stop_scheduler()
5✔
208
        self.assertEqual(self.scheduler.join(10), None)
5✔
209
        self.assertEqual(self.scheduler.is_running(), False)
5✔
210
        self.assert_raises(colony.AssertionError, lambda: self.scheduler.add_callable(lambda: 1))
5✔
211

212
        values = dict()
5✔
213

214
        def update_values():
5✔
215
            values["a"] = 1
×
216

217
        self.assertEqual(values, dict())
5✔
218

219
        identifier = self.scheduler.add_callable(update_values, verify = False)
5✔
220
        self.scheduler.wait_callable(identifier)
5✔
221
        self.assertEqual(values, dict())
5✔
222

223
        self.assert_raises(RuntimeError, self.scheduler.start_scheduler)
5✔
224

225
    def test_exception_handler(self):
5✔
226
        """
227
        Tests that the exception handler is properly handling
228
        exceptions raised in the callable execution.
229
        """
230

231
        self.assertEqual(self.scheduler.is_running(), True)
5✔
232
        self.assertEqual(self.scheduler.exception_handler, None)
5✔
233

234
        values = dict()
5✔
235

236
        def update_values_raise():
5✔
237
            values["a"] = 1
5✔
238
            raise Exception()
5✔
239

240
        identifier = self.scheduler.add_callable(update_values_raise)
5✔
241
        self.scheduler.wait_callable(identifier)
5✔
242
        self.assertEqual(values, dict(a = 1))
5✔
243
        self.assertEqual(self.scheduler.is_running(pedantic = True), True)
5✔
244

245
        def exception_handler(callable, exception):
5✔
246
            values["callable"] = callable
5✔
247
            values["exception"] = exception.__class__
5✔
248

249
        self.scheduler.set_exception_handler(exception_handler)
5✔
250

251
        identifier = self.scheduler.add_callable(update_values_raise)
5✔
252
        self.scheduler.wait_callable(identifier)
5✔
253
        self.assertEqual(
5✔
254
            values,
255
            dict(
256
                a = 1,
257
                callable = update_values_raise,
258
                exception = Exception
259
            )
260
        )
261
        self.assertEqual(self.scheduler.is_running(pedantic = True), True)
5✔
262

263
    def test_waiting(self):
5✔
264
        """
265
        Tests the waiting operation, specially for edge cases.
266
        """
267

268
        self.assertEqual(self.scheduler.is_running(), True)
5✔
269

270
        values = dict()
5✔
271

272
        def update_values_1():
5✔
273
            values["a"] = 1
5✔
274

275
        self.assertEqual(values, dict())
5✔
276

277
        identifier = self.scheduler.add_callable(update_values_1)
5✔
278
        self.scheduler.wait_callable(identifier)
5✔
279
        self.assertEqual(identifier, 1)
5✔
280
        self.assertEqual(values, dict(a = 1))
5✔
281

282
        values = dict()
5✔
283

284
        def update_values_2():
5✔
285
            values["a"] = 2
5✔
286

287
        self.assertEqual(values, dict())
5✔
288

289
        identifier = self.scheduler.add_callable(update_values_2)
5✔
290
        time.sleep(0.1)
5✔
291
        self.scheduler.wait_callable(identifier)
5✔
292
        self.assertEqual(identifier, 2)
5✔
293
        self.assertEqual(values, dict(a = 2))
5✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc