1#! /usr/bin/env python 2# -*- coding: utf-8 -*- 3# vi:ts=4:et 4 5from . import localhost 6import flaky 7import pycurl 8import unittest, signal 9import time as _time 10 11from . import appmanager 12from . import util 13 14setup_module, teardown_module = appmanager.setup(('app', 8380)) 15 16@flaky.flaky(max_runs=3) 17class PauseTest(unittest.TestCase): 18 def setUp(self): 19 self.curl = util.DefaultCurl() 20 21 def tearDown(self): 22 self.curl.close() 23 24 def test_pause_via_call(self): 25 self.check_pause(True) 26 27 def test_pause_via_return(self): 28 self.check_pause(False) 29 30 @util.only_unix 31 def check_pause(self, call): 32 # the app sleeps for 0.5 seconds 33 self.curl.setopt(pycurl.URL, 'http://%s:8380/pause' % localhost) 34 sio = util.BytesIO() 35 state = dict(paused=False, resumed=False) 36 if call: 37 def writefunc(data): 38 rv = sio.write(data) 39 if not state['paused']: 40 self.curl.pause(pycurl.PAUSE_ALL) 41 state['paused'] = True 42 return rv 43 else: 44 def writefunc(data): 45 if not state['paused']: 46 # cannot write to sio here, because 47 # curl takes pause return value to mean that 48 # nothing was written 49 state['paused'] = True 50 return pycurl.READFUNC_PAUSE 51 else: 52 return sio.write(data) 53 def resume(*args): 54 state['resumed'] = True 55 self.curl.pause(pycurl.PAUSE_CONT) 56 signal.signal(signal.SIGALRM, resume) 57 # alarm for 1 second which is 0.5 seconds more than the server side 58 # should sleep for 59 signal.alarm(1) 60 start = _time.time() 61 self.curl.setopt(pycurl.WRITEFUNCTION, writefunc) 62 63 m = pycurl.CurlMulti() 64 m.add_handle(self.curl) 65 66 # Number of seconds to wait for a timeout to happen 67 SELECT_TIMEOUT = 1.0 68 69 # Stir the state machine into action 70 while 1: 71 ret, num_handles = m.perform() 72 if ret != pycurl.E_CALL_MULTI_PERFORM: 73 break 74 75 # Keep going until all the connections have terminated 76 while num_handles: 77 # The select method uses fdset internally to determine which file descriptors 78 # to check. 79 m.select(SELECT_TIMEOUT) 80 while 1: 81 if _time.time() - start > 2: 82 # test is taking too long, fail 83 assert False, 'Test is taking too long' 84 ret, num_handles = m.perform() 85 if ret != pycurl.E_CALL_MULTI_PERFORM: 86 break 87 88 # Cleanup 89 m.remove_handle(self.curl) 90 m.close() 91 92 self.assertEqual('part1part2', sio.getvalue().decode()) 93 end = _time.time() 94 # check that client side waited 95 self.assertTrue(end-start > 1) 96 97 assert state['resumed'] 98