6 from eventlet.support import six
7 from tests import LimitedTestCase, main, run_python, skip_with_pyevent
10 base_module_contents = """
13 import urllib.request as urllib
16 print("base {0} {1}".format(socket, urllib))
19 patching_module_contents = """
20 from eventlet.green import socket
21 from eventlet.green import urllib
22 from eventlet import patcher
23 print('patcher {0} {1}'.format(socket, urllib))
24 patcher.inject('base', globals(), ('socket', socket), ('urllib', urllib))
28 import_module_contents = """
31 print("importing {0} {1} {2} {3}".format(patching, socket, patching.socket, patching.urllib))
35 class ProcessBase(LimitedTestCase):
36 TEST_TIMEOUT = 3 # starting processes is time-consuming
39 super(ProcessBase, self).setUp()
40 self._saved_syspath = sys.path
41 self.tempdir = tempfile.mkdtemp('_patcher_test')
44 super(ProcessBase, self).tearDown()
45 sys.path = self._saved_syspath
46 shutil.rmtree(self.tempdir)
48 def write_to_tempfile(self, name, contents):
49 filename = os.path.join(self.tempdir, name)
50 if not filename.endswith('.py'):
51 filename = filename + '.py'
52 with open(filename, "w") as fd:
55 def launch_subprocess(self, filename):
56 path = os.path.join(self.tempdir, filename)
57 output = run_python(path)
59 output = output.decode('utf-8')
63 lines = output.split(separator)
66 def run_script(self, contents, modname=None):
69 self.write_to_tempfile(modname, contents)
70 return self.launch_subprocess(modname)
73 class ImportPatched(ProcessBase):
74 def test_patch_a_module(self):
75 self.write_to_tempfile("base", base_module_contents)
76 self.write_to_tempfile("patching", patching_module_contents)
77 self.write_to_tempfile("importing", import_module_contents)
78 output, lines = self.launch_subprocess('importing.py')
79 assert lines[0].startswith('patcher'), repr(output)
80 assert lines[1].startswith('base'), repr(output)
81 assert lines[2].startswith('importing'), repr(output)
82 assert 'eventlet.green.socket' in lines[1], repr(output)
83 assert 'eventlet.green.urllib' in lines[1], repr(output)
84 assert 'eventlet.green.socket' in lines[2], repr(output)
85 assert 'eventlet.green.urllib' in lines[2], repr(output)
86 assert 'eventlet.green.httplib' not in lines[2], repr(output)
88 def test_import_patched_defaults(self):
89 self.write_to_tempfile("base", base_module_contents)
91 from eventlet import patcher
92 base = patcher.import_patched('base')
93 print("newmod {0} {1} {2}".format(base, base.socket, base.urllib.socket.socket))
95 self.write_to_tempfile("newmod", new_mod)
96 output, lines = self.launch_subprocess('newmod.py')
97 assert lines[0].startswith('base'), repr(output)
98 assert lines[1].startswith('newmod'), repr(output)
99 assert 'eventlet.green.socket' in lines[1], repr(output)
100 assert 'GreenSocket' in lines[1], repr(output)
103 class MonkeyPatch(ProcessBase):
104 def test_patched_modules(self):
106 from eventlet import patcher
107 patcher.monkey_patch()
110 import urllib.request as urllib
113 print("newmod {0} {1}".format(socket.socket, urllib.socket.socket))
115 self.write_to_tempfile("newmod", new_mod)
116 output, lines = self.launch_subprocess('newmod.py')
117 assert lines[0].startswith('newmod'), repr(output)
118 self.assertEqual(lines[0].count('GreenSocket'), 2, repr(output))
120 def test_early_patching(self):
122 from eventlet import patcher
123 patcher.monkey_patch()
128 self.write_to_tempfile("newmod", new_mod)
129 output, lines = self.launch_subprocess('newmod.py')
130 self.assertEqual(len(lines), 2, repr(output))
131 assert lines[0].startswith('newmod'), repr(output)
133 def test_late_patching(self):
137 from eventlet import patcher
138 patcher.monkey_patch()
142 self.write_to_tempfile("newmod", new_mod)
143 output, lines = self.launch_subprocess('newmod.py')
144 self.assertEqual(len(lines), 2, repr(output))
145 assert lines[0].startswith('newmod'), repr(output)
147 def test_typeerror(self):
149 from eventlet import patcher
150 patcher.monkey_patch(finagle=True)
152 self.write_to_tempfile("newmod", new_mod)
153 output, lines = self.launch_subprocess('newmod.py')
154 assert lines[-2].startswith('TypeError'), repr(output)
155 assert 'finagle' in lines[-2], repr(output)
157 def assert_boolean_logic(self, call, expected, not_expected=''):
158 expected_list = ", ".join(['"%s"' % x for x in expected.split(',') if len(x)])
159 not_expected_list = ", ".join(['"%s"' % x for x in not_expected.split(',') if len(x)])
161 from eventlet import patcher
164 assert patcher.is_monkey_patched(mod), mod
166 assert not patcher.is_monkey_patched(mod), mod
167 print("already_patched {0}".format(",".join(sorted(patcher.already_patched.keys()))))
168 """ % (call, expected_list, not_expected_list)
169 self.write_to_tempfile("newmod", new_mod)
170 output, lines = self.launch_subprocess('newmod.py')
171 ap = 'already_patched'
172 assert lines[0].startswith(ap), repr(output)
173 patched_modules = lines[0][len(ap):].strip()
174 # psycopg might or might not be patched based on installed modules
175 patched_modules = patched_modules.replace("psycopg,", "")
177 patched_modules = patched_modules.replace("MySQLdb,", "")
179 patched_modules, expected,
180 "Logic:%s\nExpected: %s != %s" % (call, expected, patched_modules))
182 def test_boolean(self):
183 self.assert_boolean_logic("patcher.monkey_patch()",
184 'os,select,socket,thread,time')
186 def test_boolean_all(self):
187 self.assert_boolean_logic("patcher.monkey_patch(all=True)",
188 'os,select,socket,thread,time')
190 def test_boolean_all_single(self):
191 self.assert_boolean_logic("patcher.monkey_patch(all=True, socket=True)",
192 'os,select,socket,thread,time')
194 def test_boolean_all_negative(self):
195 self.assert_boolean_logic(
196 "patcher.monkey_patch(all=False, socket=False, select=True)",
199 def test_boolean_single(self):
200 self.assert_boolean_logic("patcher.monkey_patch(socket=True)",
203 def test_boolean_double(self):
204 self.assert_boolean_logic("patcher.monkey_patch(socket=True, select=True)",
207 def test_boolean_negative(self):
208 self.assert_boolean_logic("patcher.monkey_patch(socket=False)",
209 'os,select,thread,time')
211 def test_boolean_negative2(self):
212 self.assert_boolean_logic("patcher.monkey_patch(socket=False, time=False)",
215 def test_conflicting_specifications(self):
216 self.assert_boolean_logic("patcher.monkey_patch(socket=False, select=True)",
220 test_monkey_patch_threading = """
221 def test_monkey_patch_threading():
225 from eventlet.support import six
226 for i in six.moves.range(1000):
231 tpool.execute(time.sleep, 0.5)
234 w1 = eventlet.spawn(do_sleep)
237 assert tickcount[0] > 900
242 class Tpool(ProcessBase):
246 def test_simple(self):
249 from eventlet import patcher
250 patcher.monkey_patch()
251 from eventlet import tpool
252 print("newmod {0}".format(tpool.execute(len, "hi")))
253 print("newmod {0}".format(tpool.execute(len, "hi2")))
256 self.write_to_tempfile("newmod", new_mod)
257 output, lines = self.launch_subprocess('newmod.py')
258 self.assertEqual(len(lines), 3, output)
259 assert lines[0].startswith('newmod'), repr(output)
260 assert '2' in lines[0], repr(output)
261 assert '3' in lines[1], repr(output)
264 def test_unpatched_thread(self):
265 new_mod = """import eventlet
266 eventlet.monkey_patch(time=False, thread=False)
267 from eventlet import tpool
270 new_mod += test_monkey_patch_threading
271 new_mod += "\ntest_monkey_patch_threading()\n"
272 self.write_to_tempfile("newmod", new_mod)
273 output, lines = self.launch_subprocess('newmod.py')
274 self.assertEqual(len(lines), 2, lines)
277 def test_patched_thread(self):
278 new_mod = """import eventlet
279 eventlet.monkey_patch(time=False, thread=True)
280 from eventlet import tpool
283 new_mod += test_monkey_patch_threading
284 new_mod += "\ntest_monkey_patch_threading()\n"
285 self.write_to_tempfile("newmod", new_mod)
286 output, lines = self.launch_subprocess('newmod.py')
287 self.assertEqual(len(lines), 2, "\n".join(lines))
290 class Subprocess(ProcessBase):
291 def test_monkeypatched_subprocess(self):
292 new_mod = """import eventlet
293 eventlet.monkey_patch()
294 from eventlet.green import subprocess
296 subprocess.Popen(['true'], stdin=subprocess.PIPE)
299 self.write_to_tempfile("newmod", new_mod)
300 output, lines = self.launch_subprocess('newmod')
301 self.assertEqual(output, "done\n", output)
304 class Threading(ProcessBase):
305 def test_orig_thread(self):
306 new_mod = """import eventlet
307 eventlet.monkey_patch()
308 from eventlet import patcher
310 _threading = patcher.original('threading')
312 print(repr(threading.currentThread()))
313 t = _threading.Thread(target=test)
316 print(len(threading._active))
317 print(len(_threading._active))
319 self.write_to_tempfile("newmod", new_mod)
320 output, lines = self.launch_subprocess('newmod')
321 self.assertEqual(len(lines), 4, "\n".join(lines))
322 assert lines[0].startswith('<Thread'), lines[0]
323 self.assertEqual(lines[1], "1", lines[1])
324 self.assertEqual(lines[2], "1", lines[2])
326 def test_threading(self):
327 new_mod = """import eventlet
328 eventlet.monkey_patch()
331 print(repr(threading.currentThread()))
332 t = threading.Thread(target=test)
335 print(len(threading._active))
337 self.write_to_tempfile("newmod", new_mod)
338 output, lines = self.launch_subprocess('newmod')
339 self.assertEqual(len(lines), 3, "\n".join(lines))
340 assert lines[0].startswith('<_MainThread'), lines[0]
341 self.assertEqual(lines[1], "1", lines[1])
343 def test_tpool(self):
344 new_mod = """import eventlet
345 eventlet.monkey_patch()
346 from eventlet import tpool
349 print(repr(threading.currentThread()))
351 print(len(threading._active))
353 self.write_to_tempfile("newmod", new_mod)
354 output, lines = self.launch_subprocess('newmod')
355 self.assertEqual(len(lines), 3, "\n".join(lines))
356 assert lines[0].startswith('<Thread'), lines[0]
357 self.assertEqual(lines[1], "1", lines[1])
359 def test_greenlet(self):
360 new_mod = """import eventlet
361 eventlet.monkey_patch()
362 from eventlet import event
366 print(repr(threading.currentThread()))
368 eventlet.spawn_n(test)
370 print(len(threading._active))
372 self.write_to_tempfile("newmod", new_mod)
373 output, lines = self.launch_subprocess('newmod')
374 self.assertEqual(len(lines), 3, "\n".join(lines))
375 assert lines[0].startswith('<_MainThread'), lines[0]
376 self.assertEqual(lines[1], "1", lines[1])
378 def test_greenthread(self):
379 new_mod = """import eventlet
380 eventlet.monkey_patch()
383 print(repr(threading.currentThread()))
384 t = eventlet.spawn(test)
386 print(len(threading._active))
388 self.write_to_tempfile("newmod", new_mod)
389 output, lines = self.launch_subprocess('newmod')
390 self.assertEqual(len(lines), 3, "\n".join(lines))
391 assert lines[0].startswith('<_GreenThread'), lines[0]
392 self.assertEqual(lines[1], "1", lines[1])
394 def test_keyerror(self):
395 new_mod = """import eventlet
396 eventlet.monkey_patch()
398 self.write_to_tempfile("newmod", new_mod)
399 output, lines = self.launch_subprocess('newmod')
400 self.assertEqual(len(lines), 1, "\n".join(lines))
403 class Os(ProcessBase):
404 def test_waitpid(self):
405 new_mod = """import subprocess
407 eventlet.monkey_patch(all=False, os=True)
408 process = subprocess.Popen("sleep 0.1 && false", shell=True)
409 print(process.wait())"""
410 self.write_to_tempfile("newmod", new_mod)
411 output, lines = self.launch_subprocess('newmod')
412 self.assertEqual(len(lines), 2, "\n".join(lines))
413 self.assertEqual('1', lines[0], repr(output))
416 class GreenThreadWrapper(ProcessBase):
417 prologue = """import eventlet
418 eventlet.monkey_patch()
421 t = threading.currentThread()
424 t = eventlet.spawn(test)
429 self.write_to_tempfile("newmod", self.prologue + """
432 t2 = threading.currentThread()
433 eventlet.spawn(test2)
434 """ + self.epilogue + """
438 output, lines = self.launch_subprocess('newmod')
439 self.assertEqual(len(lines), 2, "\n".join(lines))
440 assert lines[0].startswith('<_GreenThread'), lines[0]
443 self.write_to_tempfile("newmod", self.prologue + """
456 output, lines = self.launch_subprocess('newmod')
457 self.assertEqual(len(lines), 10, "\n".join(lines))
458 for i in range(0, 3):
459 self.assertEqual(lines[i], "GreenThread-1", lines[i])
460 for i in range(3, 6):
461 self.assertEqual(lines[i], "foo", lines[i])
462 for i in range(6, 9):
463 self.assertEqual(lines[i], "bar", lines[i])
465 def test_ident(self):
466 self.write_to_tempfile("newmod", self.prologue + """
470 output, lines = self.launch_subprocess('newmod')
471 self.assertEqual(len(lines), 3, "\n".join(lines))
472 self.assertEqual(lines[0], lines[1])
474 def test_is_alive(self):
475 self.write_to_tempfile("newmod", self.prologue + """
479 output, lines = self.launch_subprocess('newmod')
480 self.assertEqual(len(lines), 3, "\n".join(lines))
481 self.assertEqual(lines[0], "True", lines[0])
482 self.assertEqual(lines[1], "True", lines[1])
484 def test_is_daemon(self):
485 self.write_to_tempfile("newmod", self.prologue + """
489 output, lines = self.launch_subprocess('newmod')
490 self.assertEqual(len(lines), 3, "\n".join(lines))
491 self.assertEqual(lines[0], "True", lines[0])
492 self.assertEqual(lines[1], "True", lines[1])
495 def test_importlib_lock():
496 output = run_python('tests/patcher_test_importlib_lock.py')
497 assert output.rstrip() == b'ok'
500 if __name__ == '__main__':