def test_block(self): b = wspbus.Bus() self.log(b) def f(): time.sleep(0.2) b.exit() def g(): time.sleep(0.4) threading.Thread(target=f).start() threading.Thread(target=g).start() threads = [t for t in threading.enumerate() if not get_daemon(t)] self.assertEqual(len(threads), 3) b.block() # The block method MUST wait for the EXITING state. self.assertEqual(b.state, b.states.EXITING) # The block method MUST wait for ALL non-main, non-daemon threads to # finish. threads = [t for t in threading.enumerate() if not get_daemon(t)] self.assertEqual(len(threads), 1) # The last message will mention an indeterminable thread name; ignore # it self.assertEqual(self._log_entries[:-1], [ 'Bus STOPPING', 'Bus STOPPED', 'Bus EXITING', 'Bus EXITED', 'Waiting for child threads to terminate...' ])
def stop(server): server.stop() server.setLastTest() # there was a ton of racy failures in REST tools because of # how much global state cherrypy has. this resets it # Also, it sucks I had to copy/paste this from # https://bitbucket.org/cherrypy/cherrypy/src/9720342ad159/cherrypy/__init__.py # but reload() doesn't have the right semantics cherrybus.bus = cherrybus.Bus() cherrypy.engine = cherrybus.bus cherrypy.engine.timeout_monitor = cherrypy._TimeoutMonitor(cherrypy.engine) cherrypy.engine.timeout_monitor.subscribe() cherrypy.engine.autoreload = cherrypy.process.plugins.Autoreloader( cherrypy.engine) cherrypy.engine.autoreload.subscribe() cherrypy.engine.thread_manager = cherrypy.process.plugins.ThreadManager( cherrypy.engine) cherrypy.engine.thread_manager.subscribe() cherrypy.engine.signal_handler = cherrypy.process.plugins.SignalHandler( cherrypy.engine) cherrypy.engine.subscribe('log', cherrypy._buslog) from cherrypy import _cpserver cherrypy.server = _cpserver.Server() cherrypy.server.subscribe() cherrypy.checker = cherrypy._cpchecker.Checker() cherrypy.engine.subscribe('start', cherrypy.checker)
def test_block(self): b = wspbus.Bus() self.log(b) def f(): time.sleep(0.2) b.exit() def g(): time.sleep(0.4) threading.Thread(target=f).start() threading.Thread(target=g).start() self.assertEqual(len(threading.enumerate()), 3) b.block() # The block method MUST wait for the EXITING state. self.assertEqual(b.state, b.states.EXITING) # The block method MUST wait for ALL non-main threads to finish. self.assertEqual(len(threading.enumerate()), 1) self.assertLog([ 'Bus STOPPING', 'Bus STOPPED', 'Bus EXITING', 'Bus EXITED', 'Waiting for child threads to terminate...' ])
def test_graceful(self): b = wspbus.Bus() self.log(b) self.responses = [] num = 3 for index in range(num): b.subscribe('graceful', self.get_listener('graceful', index)) b.graceful() self.assertEqual(set(self.responses), set([ msg % (i, 'graceful', None) for i in range(num) ])) self.assertLog(['Bus graceful'])
def test_wait_publishes_periodically(self): bus = wspbus.Bus() callback = unittest.mock.MagicMock() bus.subscribe('main', callback) def set_start(): time.sleep(0.05) bus.start() threading.Thread(target=set_start).start() bus.wait(bus.states.STARTED, interval=0.01, channel='main') assert callback.call_count > 3
def test_stop(self): b = wspbus.Bus() self.log(b) self.responses = [] num = 3 for index in range(num): b.subscribe('stop', self.get_listener('stop', index)) b.stop() self.assertEqual(set(self.responses), set([ msg % (i, 'stop', None) for i in range(num) ])) self.assertEqual(b.state, b.states.STOPPED) self.assertLog(['Bus STOPPING', 'Bus STOPPED'])
def test_listener_errors(self): b = wspbus.Bus() self.responses, expected = [], [] channels = [ c for c in b.listeners if c != 'log' ] for channel in channels: b.subscribe(channel, self.get_listener(channel, 1)) b.subscribe(channel, lambda : None, priority=20) for channel in channels: self.assertRaises(wspbus.ChannelFailures, b.publish, channel, 123) expected.append(msg % (1, channel, 123)) self.assertEqual(self.responses, expected)
def test_builtin_channels(self): b = wspbus.Bus() self.responses, expected = [], [] for channel in b.listeners: for index, priority in enumerate([100, 50, 0, 51]): b.subscribe(channel, self.get_listener(channel, index), priority) for channel in b.listeners: b.publish(channel) expected.extend([msg % (i, channel, None) for i in (2, 1, 3, 0)]) b.publish(channel, arg=79347) expected.extend([msg % (i, channel, 79347) for i in (2, 1, 3, 0)]) self.assertEqual(self.responses, expected)
def test_start(self): b = wspbus.Bus() self.log(b) self.responses = [] num = 3 for index in range(num): b.subscribe('start', self.get_listener('start', index)) b.start() try: self.assertEqual(set(self.responses), set([ msg % (i, 'start', None) for i in range(num) ])) self.assertEqual(b.state, b.states.STARTED) self.assertLog(['Bus STARTING', 'Bus STARTED']) finally: b.exit()
def test_wait(self): b = wspbus.Bus() def f(method): time.sleep(0.2) getattr(b, method)() for method, states in [('start', [b.states.STARTED]), ('stop', [b.states.STOPPED]), ('start', [b.states.STARTING, b.states.STARTED]), ('exit', [b.states.EXITING])]: threading.Thread(target=f, args=(method,)).start() b.wait(states) if b.state not in states: self.fail('State %r not in %r' % (b.state, states))
def test_custom_channels(self): b = wspbus.Bus() self.responses, expected = [], [] custom_listeners = ('hugh', 'louis', 'dewey') for channel in custom_listeners: for index, priority in enumerate([None, 10, 60, 40]): b.subscribe(channel, self.get_listener(channel, index), priority) for channel in custom_listeners: b.publish(channel, 'ah so') expected.extend( [msg % (i, channel, 'ah so') for i in (1, 3, 0, 2)]) b.publish(channel) expected.extend([msg % (i, channel, None) for i in (1, 3, 0, 2)]) self.assertEqual(self.responses, expected)
def test_stop(self): b = wspbus.Bus() self.log(b) self.responses = [] num = 3 for index in range(num): b.subscribe('stop', self.get_listener('stop', index)) b.stop() # The stop method MUST call all 'stop' listeners. self.assertEqual(set(self.responses), set([msg % (i, 'stop', None) for i in range(num)])) # The stop method MUST move the state to STOPPED self.assertEqual(b.state, b.states.STOPPED) # The stop method MUST log its states. self.assertLog(['Bus STOPPING', 'Bus STOPPED'])
def test_start_with_callback(self): b = wspbus.Bus() self.log(b) try: events = [] def f(*args, **kwargs): events.append(('f', args, kwargs)) def g(): events.append('g') b.subscribe('start', g) b.start_with_callback(f, (1, 3, 5), {'foo': 'bar'}) time.sleep(0.2) self.assertEqual(b.state, b.states.STARTED) self.assertEqual(events, ['g', ('f', (1, 3, 5), {'foo': 'bar'})]) finally: b.exit()
def test_log(self): b = wspbus.Bus() self.log(b) self.assertLog([]) expected = [] for msg in ["O mah darlin'"] * 3 + ['Clementiiiiiiiine']: b.log(msg) expected.append(msg) self.assertLog(expected) try: foo except NameError: b.log('You are lost and gone forever', traceback=True) lastmsg = self._log_entries[-1] if 'Traceback' not in lastmsg or 'NameError' not in lastmsg: self.fail('Last log message %r did not contain the expected traceback.' % lastmsg) else: self.fail('NameError was not raised as expected.')
def test_exit(self): b = wspbus.Bus() self.log(b) self.responses = [] num = 3 for index in range(num): b.subscribe('stop', self.get_listener('stop', index)) b.subscribe('exit', self.get_listener('exit', index)) b.exit() # The exit method MUST call all 'stop' listeners, # and then all 'exit' listeners. self.assertEqual(set(self.responses), set([msg % (i, 'stop', None) for i in range(num)] + [msg % (i, 'exit', None) for i in range(num)])) # The exit method MUST move the state to EXITING self.assertEqual(b.state, b.states.EXITING) # The exit method MUST log its states. self.assertLog( ['Bus STOPPING', 'Bus STOPPED', 'Bus EXITING', 'Bus EXITED'])
def test_start_with_callback(self): b = wspbus.Bus() self.log(b) try: events = [] def f(*args, **kwargs): events.append(('f', args, kwargs)) def g(): events.append('g') b.subscribe('start', g) b.start_with_callback(f, (1, 3, 5), {'foo': 'bar'}) # Give wait() time to run f() time.sleep(0.2) # The callback method MUST wait for the STARTED state. self.assertEqual(b.state, b.states.STARTED) # The callback method MUST run after all start methods. self.assertEqual(events, ['g', ('f', (1, 3, 5), {'foo': 'bar'})]) finally: b.exit()
def test_log(self): b = wspbus.Bus() self.log(b) self.assertLog([]) # Try a normal message. expected = [] for msg in ["O mah darlin'"] * 3 + ["Clementiiiiiiiine"]: b.log(msg) expected.append(msg) self.assertLog(expected) # Try an error message try: foo except NameError: b.log("You are lost and gone forever", traceback=True) lastmsg = self._log_entries[-1] if "Traceback" not in lastmsg or "NameError" not in lastmsg: self.fail("Last log message %r did not contain " "the expected traceback." % lastmsg) else: self.fail("NameError was not raised as expected.")
def test_block(self): b = wspbus.Bus() self.log(b) def f(): time.sleep(0.2) b.exit() def g(): time.sleep(0.4) threading.Thread(target=f).start() threading.Thread(target=g).start() threads = [t for t in threading.enumerate() if not get_daemon(t)] self.assertEqual(len(threads), 3) b.block() self.assertEqual(b.state, b.states.EXITING) threads = [t for t in threading.enumerate() if not get_daemon(t)] self.assertEqual(len(threads), 1) self.assertEqual(self._log_entries[:-1], [ 'Bus STOPPING', 'Bus STOPPED', 'Bus EXITING', 'Bus EXITED', 'Waiting for child threads to terminate...' ])
def test_start(self): b = wspbus.Bus() self.log(b) self.responses = [] num = 3 for index in range(num): b.subscribe('start', self.get_listener('start', index)) b.start() try: # The start method MUST call all 'start' listeners. self.assertEqual( set(self.responses), set([msg % (i, 'start', None) for i in range(num)])) # The start method MUST move the state to STARTED # (or EXITING, if errors occur) self.assertEqual(b.state, b.states.STARTED) # The start method MUST log its states. self.assertLog(['Bus STARTING', 'Bus STARTED']) finally: # Exit so the atexit handler doesn't complain. b.exit()
def tearDown(self): if self.initRoot: self.rt.stop() self.rt.setLastTest() # there was a ton of racy failures in REST tools because of # how much global state cherrypy has. this resets it # Also, it sucks I had to copy/paste this from # https://bitbucket.org/cherrypy/cherrypy/src/9720342ad159/cherrypy/__init__.py # but reload() doesn't have the right semantics cherrybus.bus = cherrybus.Bus() cherrypy.engine = cherrybus.bus # This class has apparently been deprecated in the newer versions # cherrypy.engine.timeout_monitor = cherrypy._TimeoutMonitor(cherrypy.engine) # cherrypy.engine.timeout_monitor.subscribe() cherrypy.engine.autoreload = cherrypy.process.plugins.Autoreloader(cherrypy.engine) cherrypy.engine.autoreload.subscribe() cherrypy.engine.thread_manager = cherrypy.process.plugins.ThreadManager(cherrypy.engine) cherrypy.engine.thread_manager.subscribe() cherrypy.engine.signal_handler = cherrypy.process.plugins.SignalHandler(cherrypy.engine) cherrypy.engine.subscribe('log', cherrypy._buslog) from cherrypy import _cpserver cherrypy.server = _cpserver.Server() cherrypy.server.subscribe() cherrypy.checker = cherrypy._cpchecker.Checker() cherrypy.engine.subscribe('start', cherrypy.checker) if self.schemaModules: self.testInit.clearDatabase() self.config = None return
def bus(): """Return a wspbus instance.""" return wspbus.Bus()