importosimportsysimportthreadingimporttimeimporttesttest.prefer_parent_path()importcherrypyclassRoot:defindex(self):return"Hello World"index.exposed=Truedefctrlc(self):raiseKeyboardInterrupt()ctrlc.exposed=Truedefrestart(self):cherrypy.engine.restart()return"app was restarted succesfully"restart.exposed=Truedefblock_explicit(self):whileTrue:ifcherrypy.response.timed_out:cherrypy.response.timed_out=Falsereturn"broken!"time.sleep(0.1)block_explicit.exposed=Truedefblock_implicit(self):raisecherrypy.InternalRedirect("/block_implicit")block_implicit.exposed=Trueblock_implicit._cp_config={'recursive_redirect':True}cherrypy.tree.mount(Root())cherrypy.config.update({'log_to_screen':False,'environment':'production','deadlock_poll_freq':1,'deadlock_timeout':2,})classDependency:def__init__(self):self.running=Falseself.startcount=0self.threads={}defstart(self):self.running=Trueself.startcount+=1defstop(self):self.running=Falsedefstartthread(self,thread_id):self.threads[thread_id]=Nonedefstopthread(self,thread_id):delself.threads[thread_id]importhelperclassServerStateTests(helper.CPWebCase):deftest_0_NormalStateFlow(self):ifnotself.server_class:# Without having called "cherrypy.engine.start()", we should# get a 503 Service Unavailable response.self.getPage("/")self.assertStatus(503)# And our db_connection should not be runningself.assertEqual(db_connection.running,False)self.assertEqual(db_connection.startcount,0)self.assertEqual(len(db_connection.threads),0)# Test server startcherrypy.server.quickstart(self.server_class)cherrypy.engine.start(blocking=False)self.assertEqual(cherrypy.engine.state,1)ifself.server_class:host=cherrypy.config.get('server.socket_host')port=cherrypy.config.get('server.socket_port')self.assertRaises(IOError,cherrypy._cpserver.check_port,host,port)# The db_connection should be running nowself.assertEqual(db_connection.running,True)self.assertEqual(db_connection.startcount,1)self.assertEqual(len(db_connection.threads),0)self.getPage("/")self.assertBody("Hello World")self.assertEqual(len(db_connection.threads),1)# Test engine stopcherrypy.engine.stop()self.assertEqual(cherrypy.engine.state,0)# Verify that the on_stop_engine function was calledself.assertEqual(db_connection.running,False)self.assertEqual(len(db_connection.threads),0)ifnotself.server_class:# Once the engine has stopped, we should get a 503# error again. (If we were running an HTTP server,# then the connection should not even be processed).self.getPage("/")self.assertStatus(503)# Block the main thread now and verify that stop() works.defstoptest():self.getPage("/")self.assertBody("Hello World")cherrypy.engine.stop()cherrypy.engine.start_with_callback(stoptest)self.assertEqual(cherrypy.engine.state,0)cherrypy.server.stop()deftest_1_Restart(self):cherrypy.server.start()cherrypy.engine.start(blocking=False)# The db_connection should be running nowself.assertEqual(db_connection.running,True)sc=db_connection.startcountself.getPage("/")self.assertBody("Hello World")self.assertEqual(len(db_connection.threads),1)# Test server restart from this threadcherrypy.engine.restart()self.assertEqual(cherrypy.engine.state,1)self.getPage("/")self.assertBody("Hello World")self.assertEqual(db_connection.running,True)self.assertEqual(db_connection.startcount,sc+1)self.assertEqual(len(db_connection.threads),1)# Test server restart from inside a page handlerself.getPage("/restart")self.assertEqual(cherrypy.engine.state,1)self.assertBody("app was restarted succesfully")self.assertEqual(db_connection.running,True)self.assertEqual(db_connection.startcount,sc+2)# Since we are requesting synchronously, is only one thread used?# Note that the "/restart" request has been flushed.self.assertEqual(len(db_connection.threads),0)cherrypy.engine.stop()self.assertEqual(cherrypy.engine.state,0)self.assertEqual(db_connection.running,False)self.assertEqual(len(db_connection.threads),0)cherrypy.server.stop()deftest_2_KeyboardInterrupt(self):ifself.server_class:# Raise a keyboard interrupt in the HTTP server's main thread.# We must start the server in this, the main threadcherrypy.engine.start(blocking=False)cherrypy.server.start()cherrypy.server.httpservers.keys()[0].interrupt=KeyboardInterruptwhilecherrypy.engine.state!=0:time.sleep(0.1)self.assertEqual(db_connection.running,False)self.assertEqual(len(db_connection.threads),0)self.assertEqual(cherrypy.engine.state,0)# Raise a keyboard interrupt in a page handler; on multithreaded# servers, this should occur in one of the worker threads.# This should raise a BadStatusLine error, since the worker# thread will just die without writing a response.cherrypy.engine.start(blocking=False)cherrypy.server.start()fromhttplibimportBadStatusLinetry:self.getPage("/ctrlc")exceptBadStatusLine:passelse:printself.bodyself.fail("AssertionError: BadStatusLine not raised")whilecherrypy.engine.state!=0:time.sleep(0.1)self.assertEqual(db_connection.running,False)self.assertEqual(len(db_connection.threads),0)deftest_3_Deadlocks(self):cherrypy.engine.start(blocking=False)cherrypy.server.start()try:self.assertNotEqual(cherrypy.engine.monitor_thread,None)# Request a "normal" page.self.assertEqual(cherrypy.engine.servings,[])self.getPage("/")self.assertBody("Hello World")# request.close is called async.whilecherrypy.engine.servings:time.sleep(0.1)# Request a page that explicitly checks itself for deadlock.# The deadlock_timeout should be 2 secs.self.getPage("/block_explicit")self.assertBody("broken!")# Request a page that implicitly breaks deadlock.# If we deadlock, we want to touch as little code as possible,# so we won't even call handle_error, just bail ASAP.self.getPage("/block_implicit")self.assertStatus(500)self.assertInBody("raise cherrypy.TimeoutError()")finally:cherrypy.engine.stop()cherrypy.server.stop()deftest_4_Autoreload(self):ifself.server_class:demoscript=os.path.join(os.getcwd(),os.path.dirname(__file__),"test_states_demo.py")# Start the demo script in a new processhost=cherrypy.config.get("server.socket_host")port=cherrypy.config.get("server.socket_port")cherrypy._cpserver.wait_for_free_port(host,port)os.spawnl(os.P_NOWAIT,sys.executable,sys.executable,demoscript,host,str(port))cherrypy._cpserver.wait_for_occupied_port(host,port)try:self.getPage("/pid")pid=self.body# Give the autoreloader time to cache the file time.time.sleep(2)# Touch the filef=open(demoscript,'ab')f.write(" ")f.close()# Give the autoreloader time to re-exec the processtime.sleep(2)cherrypy._cpserver.wait_for_occupied_port(host,port)self.getPage("/pid")self.assertNotEqual(self.body,pid)finally:# Shut down the spawned processself.getPage("/stop")db_connection=Nonedefrun(server,conf):helper.setConfig(conf)ServerStateTests.server_class=serversuite=helper.CPTestLoader.loadTestsFromTestCase(ServerStateTests)try:globaldb_connectiondb_connection=Dependency()cherrypy.engine.on_start_engine_list.append(db_connection.start)cherrypy.engine.on_stop_engine_list.append(db_connection.stop)cherrypy.engine.on_start_thread_list.append(db_connection.startthread)cherrypy.engine.on_stop_thread_list.append(db_connection.stopthread)try:importpyconquerexceptImportError:helper.CPTestRunner.run(suite)else:tr=pyconquer.Logger("cherrypy")tr.out=open(os.path.join(os.path.dirname(__file__),"state.log"),"wb")try:tr.start()helper.CPTestRunner.run(suite)finally:tr.stop()tr.out.close()finally:cherrypy.server.stop()cherrypy.engine.stop()defrun_all(host,port):conf={'server.socket_host':host,'server.socket_port':port,'server.thread_pool':10,'log_to_screen':False,'log_config':False,'environment':"production",'show_tracebacks':True,}def_run(server):printprint"Testing %s on %s:%s..."%(server,host,port)run(server,conf)_run("cherrypy._cpwsgi.WSGIServer")defrun_localhosts(port):forhostin("","127.0.0.1","localhost"):conf={'server.socket_host':host,'server.socket_port':port,'server.thread_pool':10,'log_to_screen':False,'log_config':False,'environment':"production",'show_tracebacks':True,}def_run(server):printprint"Testing %s on %s:%s..."%(server,host,port)run(server,conf)_run("cherrypy._cpwsgi.WSGIServer")if__name__=="__main__":importsyshost='127.0.0.1'port=8000iflen(sys.argv)>1:cmd=sys.argv[1]ifcmdin[prefix+atomforatomin("?","h","help")forprefixin("","-","--","\\")]:printprint"test_states.py -? -> this help page"print"test_states.py [host] [port] -> run the tests on the given host/port"print"test_states.py -localhosts [port] -> try various localhost strings"sys.exit(0)iflen(sys.argv)>2:port=int(sys.argv[2])ifcmd=="-localhosts":run_localhosts(port)sys.exit(0)host=sys.argv[1].strip("\"'")run_all(host,port)