~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_test_server.py

  • Committer: John Arbash Meinel
  • Date: 2011-10-10 13:59:22 UTC
  • mfrom: (6015.33.11 2.4)
  • mto: This revision was merged to the branch mainline in revision 6206.
  • Revision ID: john@arbash-meinel.com-20111010135922-wanbhsy9i42zm6w9
Merge bzr-2.4 into bzr.dev, resolve the small conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
112
112
        for name in
113
113
        ('TestingTCPServer', 'TestingThreadingTCPServer')]
114
114
 
115
 
    # Set by load_tests()
116
 
    server_class = None
117
 
 
118
115
    def get_server(self, server_class=None, connection_handler_class=None):
119
116
        if server_class is not None:
120
117
            self.server_class = server_class
202
199
        self.assertRaises(CantConnect, server.stop_server)
203
200
 
204
201
    def test_server_crash_while_responding(self):
205
 
        sync = threading.Event()
206
 
        sync.clear()
 
202
        # We want to ensure the exception has been caught
 
203
        caught = threading.Event()
 
204
        caught.clear()
 
205
        # The thread that will serve the client, this needs to be an attribute
 
206
        # so the handler below can modify it when it's executed (it's
 
207
        # instantiated when the request is processed)
 
208
        self.connection_thread = None
 
209
 
207
210
        class FailToRespond(Exception):
208
211
            pass
209
212
 
210
213
        class FailingDuringResponseHandler(TCPConnectionHandler):
211
214
 
212
 
            def handle_connection(self):
213
 
                req = self.readline()
214
 
                threading.currentThread().set_sync_event(sync)
 
215
            def handle_connection(request):
 
216
                req = request.readline()
 
217
                # Capture the thread and make it use 'caught' so we can wait on
 
218
                # the even that will be set when the exception is caught. We
 
219
                # also capture the thread to know where to look.
 
220
                self.connection_thread = threading.currentThread()
 
221
                self.connection_thread.set_sync_event(caught)
215
222
                raise FailToRespond()
216
223
 
217
224
        server = self.get_server(
219
226
        client = self.get_client()
220
227
        client.connect((server.host, server.port))
221
228
        client.write('ping\n')
222
 
        sync.wait()
 
229
        # Wait for the exception to be caught
 
230
        caught.wait()
223
231
        self.assertEqual('', client.read()) # connection closed
224
 
        self.assertRaises(FailToRespond, server.pending_exception)
 
232
        # Check that the connection thread did catch the exception,
 
233
        # http://pad.lv/869366 was wrongly checking the server thread which
 
234
        # works for TestingTCPServer where the connection is handled in the
 
235
        # same thread than the server one but is racy for
 
236
        # TestingThreadingTCPServer where the server thread may be in a
 
237
        # blocking accept() call (or not).
 
238
        try:
 
239
            self.connection_thread.pending_exception()
 
240
        except FailToRespond:
 
241
            # Great, the test succeeded
 
242
            pass
 
243
        else:
 
244
            # If the exception is not in the connection thread anymore, it's in
 
245
            # the server's one. 
 
246
            server.server.stopped.wait()
 
247
            # The exception is available now
 
248
            self.assertRaises(FailToRespond, server.pending_exception)
225
249
 
226
250
    def test_exception_swallowed_while_serving(self):
227
 
        sync = threading.Event()
228
 
        sync.clear()
 
251
        # We need to ensure the exception has been caught
 
252
        caught = threading.Event()
 
253
        caught.clear()
 
254
        # The thread that will serve the client, this needs to be an attribute
 
255
        # so the handler below can access it when it's executed (it's
 
256
        # instantiated when the request is processed)
 
257
        self.connection_thread = None
229
258
        class CantServe(Exception):
230
259
            pass
231
260
 
232
261
        class FailingWhileServingConnectionHandler(TCPConnectionHandler):
233
262
 
234
 
            def handle(self):
235
 
                # We want to sync with the thread that is serving the
236
 
                # connection.
237
 
                threading.currentThread().set_sync_event(sync)
 
263
            def handle(request):
 
264
                # Capture the thread and make it use 'caught' so we can wait on
 
265
                # the even that will be set when the exception is caught. We
 
266
                # also capture the thread to know where to look.
 
267
                self.connection_thread = threading.currentThread()
 
268
                self.connection_thread.set_sync_event(caught)
238
269
                raise CantServe()
239
270
 
240
271
        server = self.get_server(
244
275
        client = self.get_client()
245
276
        # Connect to the server so the exception is raised there
246
277
        client.connect((server.host, server.port))
247
 
        # Wait for the exception to propagate.
248
 
        sync.wait()
 
278
        # Wait for the exception to be caught
 
279
        caught.wait()
249
280
        self.assertEqual('', client.read()) # connection closed
250
281
        # The connection wasn't served properly but the exception should have
251
 
        # been swallowed.
 
282
        # been swallowed (see test_server_crash_while_responding remark about
 
283
        # http://pad.lv/869366 explaining why we can't check the server thread
 
284
        # here). More precisely, the exception *has* been caught and captured
 
285
        # but it is cleared when joining the thread (or trying to acquire the
 
286
        # exception) and as such won't propagate to the server thread.
 
287
        self.connection_thread.pending_exception()
252
288
        server.pending_exception()
253
289
 
254
290
    def test_handle_request_closes_if_it_doesnt_process(self):