6 from tests import LimitedTestCase, main, run_python, skip_with_pyevent
9 base_module_contents = """
12 print("base {0} {1}".format(socket, urllib))
15 patching_module_contents = """
16 from eventlet.green import socket
17 from eventlet.green import urllib
18 from eventlet import patcher
19 print('patcher {0} {1}'.format(socket, urllib))
20 patcher.inject('base', globals(), ('socket', socket), ('urllib', urllib))
24 import_module_contents = """
27 print("importing {0} {1} {2} {3}".format(patching, socket, patching.socket, patching.urllib))
31 class ProcessBase(LimitedTestCase):
32 TEST_TIMEOUT = 3 # starting processes is time-consuming
35 super(ProcessBase, self).setUp()
36 self._saved_syspath = sys.path
37 self.tempdir = tempfile.mkdtemp('_patcher_test')
40 super(ProcessBase, self).tearDown()
41 sys.path = self._saved_syspath
42 shutil.rmtree(self.tempdir)
44 def write_to_tempfile(self, name, contents):
45 filename = os.path.join(self.tempdir, name)
46 if not filename.endswith('.py'):
47 filename = filename + '.py'
48 fd = open(filename, "wb")
52 def launch_subprocess(self, filename):
53 path = os.path.join(self.tempdir, filename)
54 output = run_python(path)
55 lines = output.split("\n")
58 def run_script(self, contents, modname=None):
61 self.write_to_tempfile(modname, contents)
62 return self.launch_subprocess(modname)
65 class ImportPatched(ProcessBase):
66 def test_patch_a_module(self):
67 self.write_to_tempfile("base", base_module_contents)
68 self.write_to_tempfile("patching", patching_module_contents)
69 self.write_to_tempfile("importing", import_module_contents)
70 output, lines = self.launch_subprocess('importing.py')
71 assert lines[0].startswith('patcher'), repr(output)
72 assert lines[1].startswith('base'), repr(output)
73 assert lines[2].startswith('importing'), repr(output)
74 assert 'eventlet.green.socket' in lines[1], repr(output)
75 assert 'eventlet.green.urllib' in lines[1], repr(output)
76 assert 'eventlet.green.socket' in lines[2], repr(output)
77 assert 'eventlet.green.urllib' in lines[2], repr(output)
78 assert 'eventlet.green.httplib' not in lines[2], repr(output)
80 def test_import_patched_defaults(self):
81 self.write_to_tempfile("base", base_module_contents)
83 from eventlet import patcher
84 base = patcher.import_patched('base')
85 print("newmod {0} {1} {2}".format(base, base.socket, base.urllib.socket.socket))
87 self.write_to_tempfile("newmod", new_mod)
88 output, lines = self.launch_subprocess('newmod.py')
89 assert lines[0].startswith('base'), repr(output)
90 assert lines[1].startswith('newmod'), repr(output)
91 assert 'eventlet.green.socket' in lines[1], repr(output)
92 assert 'GreenSocket' in lines[1], repr(output)
95 class MonkeyPatch(ProcessBase):
96 def test_patched_modules(self):
98 from eventlet import patcher
99 patcher.monkey_patch()
102 print("newmod {0} {1}".format(socket.socket, urllib.socket.socket))
104 self.write_to_tempfile("newmod", new_mod)
105 output, lines = self.launch_subprocess('newmod.py')
106 assert lines[0].startswith('newmod'), repr(output)
107 self.assertEqual(lines[0].count('GreenSocket'), 2, repr(output))
109 def test_early_patching(self):
111 from eventlet import patcher
112 patcher.monkey_patch()
117 self.write_to_tempfile("newmod", new_mod)
118 output, lines = self.launch_subprocess('newmod.py')
119 self.assertEqual(len(lines), 2, repr(output))
120 assert lines[0].startswith('newmod'), repr(output)
122 def test_late_patching(self):
126 from eventlet import patcher
127 patcher.monkey_patch()
131 self.write_to_tempfile("newmod", new_mod)
132 output, lines = self.launch_subprocess('newmod.py')
133 self.assertEqual(len(lines), 2, repr(output))
134 assert lines[0].startswith('newmod'), repr(output)
136 def test_typeerror(self):
138 from eventlet import patcher
139 patcher.monkey_patch(finagle=True)
141 self.write_to_tempfile("newmod", new_mod)
142 output, lines = self.launch_subprocess('newmod.py')
143 assert lines[-2].startswith('TypeError'), repr(output)
144 assert 'finagle' in lines[-2], repr(output)
146 def assert_boolean_logic(self, call, expected, not_expected=''):
147 expected_list = ", ".join(['"%s"' % x for x in expected.split(',') if len(x)])
148 not_expected_list = ", ".join(['"%s"' % x for x in not_expected.split(',') if len(x)])
150 from eventlet import patcher
153 assert patcher.is_monkey_patched(mod), mod
155 assert not patcher.is_monkey_patched(mod), mod
156 print("already_patched {0}".format(",".join(sorted(patcher.already_patched.keys()))))
157 """ % (call, expected_list, not_expected_list)
158 self.write_to_tempfile("newmod", new_mod)
159 output, lines = self.launch_subprocess('newmod.py')
160 ap = 'already_patched'
161 assert lines[0].startswith(ap), repr(output)
162 patched_modules = lines[0][len(ap):].strip()
163 # psycopg might or might not be patched based on installed modules
164 patched_modules = patched_modules.replace("psycopg,", "")
166 patched_modules = patched_modules.replace("MySQLdb,", "")
168 patched_modules, expected,
169 "Logic:%s\nExpected: %s != %s" % (call, expected, patched_modules))
171 def test_boolean(self):
172 self.assert_boolean_logic("patcher.monkey_patch()",
173 'os,select,socket,thread,time')
175 def test_boolean_all(self):
176 self.assert_boolean_logic("patcher.monkey_patch(all=True)",
177 'os,select,socket,thread,time')
179 def test_boolean_all_single(self):
180 self.assert_boolean_logic("patcher.monkey_patch(all=True, socket=True)",
181 'os,select,socket,thread,time')
183 def test_boolean_all_negative(self):
184 self.assert_boolean_logic(
185 "patcher.monkey_patch(all=False, socket=False, select=True)",
188 def test_boolean_single(self):
189 self.assert_boolean_logic("patcher.monkey_patch(socket=True)",
192 def test_boolean_double(self):
193 self.assert_boolean_logic("patcher.monkey_patch(socket=True, select=True)",
196 def test_boolean_negative(self):
197 self.assert_boolean_logic("patcher.monkey_patch(socket=False)",
198 'os,select,thread,time')
200 def test_boolean_negative2(self):
201 self.assert_boolean_logic("patcher.monkey_patch(socket=False, time=False)",
204 def test_conflicting_specifications(self):
205 self.assert_boolean_logic("patcher.monkey_patch(socket=False, select=True)",
209 test_monkey_patch_threading = """
210 def test_monkey_patch_threading():
214 from eventlet.support import six
215 for i in six.moves.range(1000):
220 tpool.execute(time.sleep, 0.5)
223 w1 = eventlet.spawn(do_sleep)
226 assert tickcount[0] > 900
231 class Tpool(ProcessBase):
235 def test_simple(self):
238 from eventlet import patcher
239 patcher.monkey_patch()
240 from eventlet import tpool
241 print("newmod {0}".format(tpool.execute(len, "hi")))
242 print("newmod {0}".format(tpool.execute(len, "hi2")))
245 self.write_to_tempfile("newmod", new_mod)
246 output, lines = self.launch_subprocess('newmod.py')
247 self.assertEqual(len(lines), 3, output)
248 assert lines[0].startswith('newmod'), repr(output)
249 assert '2' in lines[0], repr(output)
250 assert '3' in lines[1], repr(output)
253 def test_unpatched_thread(self):
254 new_mod = """import eventlet
255 eventlet.monkey_patch(time=False, thread=False)
256 from eventlet import tpool
259 new_mod += test_monkey_patch_threading
260 new_mod += "\ntest_monkey_patch_threading()\n"
261 self.write_to_tempfile("newmod", new_mod)
262 output, lines = self.launch_subprocess('newmod.py')
263 self.assertEqual(len(lines), 2, lines)
266 def test_patched_thread(self):
267 new_mod = """import eventlet
268 eventlet.monkey_patch(time=False, thread=True)
269 from eventlet import tpool
272 new_mod += test_monkey_patch_threading
273 new_mod += "\ntest_monkey_patch_threading()\n"
274 self.write_to_tempfile("newmod", new_mod)
275 output, lines = self.launch_subprocess('newmod.py')
276 self.assertEqual(len(lines), 2, "\n".join(lines))
279 class Subprocess(ProcessBase):
280 def test_monkeypatched_subprocess(self):
281 new_mod = """import eventlet
282 eventlet.monkey_patch()
283 from eventlet.green import subprocess
285 subprocess.Popen(['true'], stdin=subprocess.PIPE)
288 self.write_to_tempfile("newmod", new_mod)
289 output, lines = self.launch_subprocess('newmod')
290 self.assertEqual(output, "done\n", output)
293 class Threading(ProcessBase):
294 def test_orig_thread(self):
295 new_mod = """import eventlet
296 eventlet.monkey_patch()
297 from eventlet import patcher
299 _threading = patcher.original('threading')
301 print(repr(threading.currentThread()))
302 t = _threading.Thread(target=test)
305 print(len(threading._active))
306 print(len(_threading._active))
308 self.write_to_tempfile("newmod", new_mod)
309 output, lines = self.launch_subprocess('newmod')
310 self.assertEqual(len(lines), 4, "\n".join(lines))
311 assert lines[0].startswith('<Thread'), lines[0]
312 self.assertEqual(lines[1], "1", lines[1])
313 self.assertEqual(lines[2], "1", lines[2])
315 def test_threading(self):
316 new_mod = """import eventlet
317 eventlet.monkey_patch()
320 print(repr(threading.currentThread()))
321 t = threading.Thread(target=test)
324 print(len(threading._active))
326 self.write_to_tempfile("newmod", new_mod)
327 output, lines = self.launch_subprocess('newmod')
328 self.assertEqual(len(lines), 3, "\n".join(lines))
329 assert lines[0].startswith('<_MainThread'), lines[0]
330 self.assertEqual(lines[1], "1", lines[1])
332 def test_tpool(self):
333 new_mod = """import eventlet
334 eventlet.monkey_patch()
335 from eventlet import tpool
338 print(repr(threading.currentThread()))
340 print(len(threading._active))
342 self.write_to_tempfile("newmod", new_mod)
343 output, lines = self.launch_subprocess('newmod')
344 self.assertEqual(len(lines), 3, "\n".join(lines))
345 assert lines[0].startswith('<Thread'), lines[0]
346 self.assertEqual(lines[1], "1", lines[1])
348 def test_greenlet(self):
349 new_mod = """import eventlet
350 eventlet.monkey_patch()
351 from eventlet import event
355 print(repr(threading.currentThread()))
357 eventlet.spawn_n(test)
359 print(len(threading._active))
361 self.write_to_tempfile("newmod", new_mod)
362 output, lines = self.launch_subprocess('newmod')
363 self.assertEqual(len(lines), 3, "\n".join(lines))
364 assert lines[0].startswith('<_MainThread'), lines[0]
365 self.assertEqual(lines[1], "1", lines[1])
367 def test_greenthread(self):
368 new_mod = """import eventlet
369 eventlet.monkey_patch()
372 print(repr(threading.currentThread()))
373 t = eventlet.spawn(test)
375 print(len(threading._active))
377 self.write_to_tempfile("newmod", new_mod)
378 output, lines = self.launch_subprocess('newmod')
379 self.assertEqual(len(lines), 3, "\n".join(lines))
380 assert lines[0].startswith('<_GreenThread'), lines[0]
381 self.assertEqual(lines[1], "1", lines[1])
383 def test_keyerror(self):
384 new_mod = """import eventlet
385 eventlet.monkey_patch()
387 self.write_to_tempfile("newmod", new_mod)
388 output, lines = self.launch_subprocess('newmod')
389 self.assertEqual(len(lines), 1, "\n".join(lines))
392 class Os(ProcessBase):
393 def test_waitpid(self):
394 new_mod = """import subprocess
396 eventlet.monkey_patch(all=False, os=True)
397 process = subprocess.Popen("sleep 0.1 && false", shell=True)
398 print(process.wait())"""
399 self.write_to_tempfile("newmod", new_mod)
400 output, lines = self.launch_subprocess('newmod')
401 self.assertEqual(len(lines), 2, "\n".join(lines))
402 self.assertEqual('1', lines[0], repr(output))
405 class GreenThreadWrapper(ProcessBase):
406 prologue = """import eventlet
407 eventlet.monkey_patch()
410 t = threading.currentThread()
413 t = eventlet.spawn(test)
418 self.write_to_tempfile("newmod", self.prologue + """
421 t2 = threading.currentThread()
422 eventlet.spawn(test2)
423 """ + self.epilogue + """
427 output, lines = self.launch_subprocess('newmod')
428 self.assertEqual(len(lines), 2, "\n".join(lines))
429 assert lines[0].startswith('<_GreenThread'), lines[0]
432 self.write_to_tempfile("newmod", self.prologue + """
445 output, lines = self.launch_subprocess('newmod')
446 self.assertEqual(len(lines), 10, "\n".join(lines))
447 for i in range(0, 3):
448 self.assertEqual(lines[i], "GreenThread-1", lines[i])
449 for i in range(3, 6):
450 self.assertEqual(lines[i], "foo", lines[i])
451 for i in range(6, 9):
452 self.assertEqual(lines[i], "bar", lines[i])
454 def test_ident(self):
455 self.write_to_tempfile("newmod", self.prologue + """
459 output, lines = self.launch_subprocess('newmod')
460 self.assertEqual(len(lines), 3, "\n".join(lines))
461 self.assertEqual(lines[0], lines[1])
463 def test_is_alive(self):
464 self.write_to_tempfile("newmod", self.prologue + """
468 output, lines = self.launch_subprocess('newmod')
469 self.assertEqual(len(lines), 3, "\n".join(lines))
470 self.assertEqual(lines[0], "True", lines[0])
471 self.assertEqual(lines[1], "True", lines[1])
473 def test_is_daemon(self):
474 self.write_to_tempfile("newmod", self.prologue + """
478 output, lines = self.launch_subprocess('newmod')
479 self.assertEqual(len(lines), 3, "\n".join(lines))
480 self.assertEqual(lines[0], "True", lines[0])
481 self.assertEqual(lines[1], "True", lines[1])
484 if __name__ == '__main__':