66
73
from twisted.python.failure import Failure
76
def return_args(*args, **kwargs):
69
80
class TestAsynchronousDecorator(MAASTestCase):
71
82
run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=5)
74
def return_args(self, *args, **kwargs):
77
84
def test_in_reactor_thread(self):
78
result = self.return_args(1, 2, three=3)
85
result = asynchronous(return_args)(1, 2, three=3)
79
86
self.assertEqual(((1, 2), {"three": 3}), result)
82
89
def test_in_other_thread(self):
83
90
def do_stuff_in_thread():
84
result = self.return_args(3, 4, five=5)
91
result = asynchronous(return_args)(3, 4, five=5)
85
92
self.assertThat(result, IsInstance(EventualResult))
86
93
return result.wait()
87
94
# Call do_stuff_in_thread() from another thread.
92
99
self.assertEqual(((3, 4), {"five": 5}), result)
105
class TestAsynchronousDecoratorWithTimeout(MAASTestCase):
107
run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=5)
109
def test_timeout_cannot_be_None(self):
110
self.assertRaises(ValueError, asynchronous, noop, timeout=None)
112
def test_timeout_cannot_be_negative(self):
113
self.assertRaises(ValueError, asynchronous, noop, timeout=-1)
115
def test_timeout_can_be_int(self):
116
self.assertThat(asynchronous(noop, timeout=1), IsCallable())
118
def test_timeout_can_be_long(self):
119
self.assertThat(asynchronous(noop, timeout=1L), IsCallable())
121
def test_timeout_can_be_float(self):
122
self.assertThat(asynchronous(noop, timeout=1.0), IsCallable())
124
def test_timeout_can_be_forever(self):
125
self.assertThat(asynchronous(noop, timeout=FOREVER), IsCallable())
128
class TestAsynchronousDecoratorWithTimeoutDefined(MAASTestCase):
130
run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=5)
133
("finite", {"timeout": random()}),
134
("forever", {"timeout": FOREVER}),
137
def test_in_reactor_thread(self):
138
return_args_async = asynchronous(return_args, self.timeout)
139
result = return_args_async(1, 2, three=3)
140
self.assertEqual(((1, 2), {"three": 3}), result)
143
def test_in_other_thread(self):
144
return_args_async = asynchronous(return_args, self.timeout)
145
# Call self.return_args from another thread.
146
result = yield deferToThread(return_args_async, 3, 4, five=5)
147
# The arguments passed back match those passed in.
148
self.assertEqual(((3, 4), {"five": 5}), result)
151
def test__passes_timeout_to_wait(self):
152
# These mocks are going to help us tell a story of a timeout.
153
run_in_reactor = self.patch(twisted_module, "run_in_reactor")
154
func_in_reactor = run_in_reactor.return_value
155
eventual_result = func_in_reactor.return_value
156
wait = eventual_result.wait
157
wait.return_value = sentinel.result
159
# Our placeholder function, and its wrapped version.
160
do_nothing = lambda: None
161
do_nothing_async = asynchronous(do_nothing, timeout=self.timeout)
163
# Call our wrapped function in a thread so that the wrapper calls back
164
# into the IO thread, via the time-out logic.
165
result = yield deferToThread(do_nothing_async)
166
self.expectThat(result, Equals(sentinel.result))
168
# Here's what happened, or should have:
169
# 1. do_nothing was wrapped by run_in_reactor, producing
171
self.assertThat(run_in_reactor, MockCalledOnceWith(do_nothing))
172
# 2. func_in_reactor was called with no arguments, because we didn't
173
# pass any, producing eventual_result.
174
self.assertThat(func_in_reactor, MockCalledOnceWith())
175
# 3. eventual_result.wait was called...
176
if self.timeout is FOREVER:
177
# ...without arguments.
178
self.assertThat(wait, MockCalledOnceWith())
180
# ...with the timeout we passed when we wrapped do_nothing.
181
self.assertThat(wait, MockCalledOnceWith(self.timeout))
95
184
class TestSynchronousDecorator(MAASTestCase):
97
186
run_tests_with = AsynchronousDeferredRunTest.make_factory(timeout=5)