Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

root/branches/cherrypy-2.1/cherrypy/test/test_states.py

Revision 709 (checked in by fumanchu, 3 years ago)

More state tests (onStart/Stop tests). Also made it more explicit that onStop's are called even if there's no HTTP server.

Line 
1 """
2 Copyright (c) 2004, CherryPy Team (team@cherrypy.org)
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8     * Redistributions of source code must retain the above copyright notice,
9       this list of conditions and the following disclaimer.
10     * Redistributions in binary form must reproduce the above copyright notice,
11       this list of conditions and the following disclaimer in the documentation
12       and/or other materials provided with the distribution.
13     * Neither the name of the CherryPy Team nor the names of its contributors
14       may be used to endorse or promote products derived from this software
15       without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
21 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 """
28
29 import time
30 import threading
31
32 import cherrypy
33
34
35 class Root:
36     def index(self):
37         return "Hello World"
38     index.exposed = True
39    
40     def ctrlc(self):
41         raise KeyboardInterrupt()
42     ctrlc.exposed = True
43    
44     def restart(self):
45         cherrypy.server.restart()
46         return "app was restarted succesfully"
47     restart.exposed = True
48
49 cherrypy.root = Root()
50 cherrypy.config.update({
51     'global': {
52         'server.logToScreen': False,
53         'server.environment': 'production',
54     },
55 })
56
57 class Dependency:
58    
59     def __init__(self):
60         self.running = False
61         self.startcount = 0
62         self.threads = {}
63    
64     def start(self):
65         self.running = True
66         self.startcount += 1
67    
68     def stop(self):
69         self.running = False
70    
71     def startthread(self, thread_id):
72         self.threads[thread_id] = None
73    
74     def stopthread(self, thread_id):
75         del self.threads[thread_id]
76
77
78 import helper
79
80 class ServerStateTests(helper.CPWebCase):
81    
82     def test_0_NormalStateFlow(self):
83         # Without having called "cherrypy.server.start()", we should
84         # get a NotReady error
85         self.assertRaises(cherrypy.NotReady, self.getPage, "/")
86        
87         # And our db_connection should not be running
88         self.assertEqual(db_connection.running, False)
89         self.assertEqual(db_connection.startcount, 0)
90         self.assertEqual(len(db_connection.threads), 0)
91        
92         # Test server start
93         cherrypy.server.start(True, self.serverClass)
94         self.assertEqual(cherrypy.server.state, 1)
95        
96         if self.serverClass:
97             host = cherrypy.config.get('server.socketHost')
98             port = cherrypy.config.get('server.socketPort')
99             self.assertRaises(IOError, cherrypy._cpserver.check_port, host, port)
100        
101         # The db_connection should be running now
102         self.assertEqual(db_connection.running, True)
103         self.assertEqual(db_connection.startcount, 1)
104         self.assertEqual(len(db_connection.threads), 0)
105        
106         self.getPage("/")
107         self.assertBody("Hello World")
108         self.assertEqual(len(db_connection.threads), 1)
109        
110         # Test server stop
111         cherrypy.server.stop()
112         self.assertEqual(cherrypy.server.state, 0)
113        
114         # Once the server has stopped, we should get a NotReady error again.
115         self.assertRaises(cherrypy.NotReady, self.getPage, "/")
116        
117         # Verify that the onStopServer function was called
118         self.assertEqual(db_connection.running, False)
119         self.assertEqual(len(db_connection.threads), 0)
120    
121     def test_1_Restart(self):
122         cherrypy.server.start(True, self.serverClass)
123        
124         # The db_connection should be running now
125         self.assertEqual(db_connection.running, True)
126         sc = db_connection.startcount
127        
128         self.getPage("/")
129         self.assertBody("Hello World")
130         self.assertEqual(len(db_connection.threads), 1)
131        
132         # Test server restart from this thread
133         cherrypy.server.restart()
134         self.assertEqual(cherrypy.server.state, 1)
135         self.getPage("/")
136         self.assertBody("Hello World")
137         self.assertEqual(db_connection.running, True)
138         self.assertEqual(db_connection.startcount, sc + 1)
139         self.assertEqual(len(db_connection.threads), 1)
140        
141         # Test server restart from inside a page handler
142         self.getPage("/restart")
143         self.assertEqual(cherrypy.server.state, 1)
144         self.assertBody("app was restarted succesfully")
145         self.assertEqual(db_connection.running, True)
146         self.assertEqual(db_connection.startcount, sc + 2)
147         # Since we are requesting synchronously, is only one thread used?
148         # Note that the "/restart" request has been flushed.
149         self.assertEqual(len(db_connection.threads), 0)
150        
151         cherrypy.server.stop()
152         self.assertEqual(cherrypy.server.state, 0)
153         self.assertEqual(db_connection.running, False)
154         self.assertEqual(len(db_connection.threads), 0)
155    
156     def test_2_KeyboardInterrupt(self):
157         if self.serverClass:
158            
159             # Raise a keyboard interrupt in the HTTP server's main thread.
160             def interrupt():
161                 cherrypy.server.wait()
162                 cherrypy.server.httpserver.interrupt = KeyboardInterrupt
163             threading.Thread(target=interrupt).start()
164            
165             # We must start the server in this, the main thread
166             cherrypy.server.start(False, self.serverClass)
167             # Time passes...
168             self.assertEqual(cherrypy.server.httpserver, None)
169             self.assertEqual(cherrypy.server.state, 0)
170             self.assertRaises(cherrypy.NotReady, self.getPage, "/")
171             self.assertEqual(db_connection.running, False)
172             self.assertEqual(len(db_connection.threads), 0)
173            
174             # Raise a keyboard interrupt in a page handler; on multithreaded
175             # servers, this should occur in one of the worker threads.
176             # This should raise a BadStatusLine error, since the worker
177             # thread will just die without writing a response.
178             def interrupt():
179                 cherrypy.server.wait()
180                 from httplib import BadStatusLine
181                 self.assertRaises(BadStatusLine, self.getPage, "/ctrlc")
182             threading.Thread(target=interrupt).start()
183            
184             cherrypy.server.start(False, self.serverClass)
185             # Time passes...
186             self.assertEqual(cherrypy.server.httpserver, None)
187             self.assertEqual(cherrypy.server.state, 0)
188             self.assertRaises(cherrypy.NotReady, self.getPage, "/")
189             self.assertEqual(db_connection.running, False)
190             self.assertEqual(len(db_connection.threads), 0)
191
192
193 db_connection = None
194
195 def run(server, conf):
196     helper.setConfig(conf)
197     ServerStateTests.serverClass = server
198     suite = helper.CPTestLoader.loadTestsFromTestCase(ServerStateTests)
199     try:
200         global db_connection
201         db_connection = Dependency()
202         cherrypy.server.onStartServerList.append(db_connection.start)
203         cherrypy.server.onStopServerList.append(db_connection.stop)
204         cherrypy.server.onStartThreadList.append(db_connection.startthread)
205         cherrypy.server.onStopThreadList.append(db_connection.stopthread)
206        
207         helper.CPTestRunner.run(suite)
208     finally:
209         cherrypy.server.stop()
210
211
212 if __name__ == "__main__":
213     conf = {'server.socketHost': '127.0.0.1',
214             'server.socketPort': 8000,
215             'server.threadPool': 10,
216             'server.logToScreen': False,
217             'server.logConfigOptions': False,
218             'server.environment': "production",
219             'server.showTracebacks': True,
220             }
221     def _run(server):
222         print
223         print "Testing %s..." % (server or "serverless")
224         run(server, conf)
225     _run(None)
226     _run("cherrypy._cpwsgi.WSGIServer")
227     _run("cherrypy._cphttpserver.PooledThreadServer")
228     conf['server.threadPool'] = 1
229     _run("cherrypy._cphttpserver.CherryHTTPServer")
Note: See TracBrowser for help on using the browser.

Hosted by WebFaction

Log in as guest/cpguest to create tickets