changeset 99:b9cdccd5fbe4 default tip

Added unit test (doctest).
author Atul Varma <varmaa@toolness.com>
date Sat, 02 May 2009 08:13:45 -0700
parents 06aa973a54c3
children
files cosocket.py openwebchat.py
diffstat 2 files changed, 72 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/cosocket.py	Sat May 02 00:47:23 2009 -0700
+++ b/cosocket.py	Sat May 02 08:13:45 2009 -0700
@@ -1,3 +1,48 @@
+'''
+    >>> IP = '127.0.0.1'
+    >>> PORT = 38424
+
+    >>> def server_coroutine():
+    ...     print 'server now listening.'
+    ...     yield until_listening((IP, PORT))
+    ...     print 'server now spawning client.'
+    ...     AsyncChatCoroutine(client_coroutine())
+    ...     print 'server now accepting connections.'
+    ...     conn, addr = yield until_connection_accepted()
+    ...     print 'server now spawning connection.'
+    ...     AsyncChatCoroutine(connection_coroutine(addr), conn)
+
+    >>> def client_coroutine():
+    ...     print 'client now connecting to server.'
+    ...     yield until_connected((IP, PORT))
+    ...     print 'client now connected, sending text.'
+    ...     yield until_sent('hai2u\\r\\n')
+    ...     print 'client waiting for response.'
+    ...     data = yield until_received(terminator = '\\r\\n')
+    ...     print 'client received response: %s' % data
+
+    >>> def connection_coroutine(addr):
+    ...     print 'server connection waiting for request.'
+    ...     data = yield until_received('\\r\\n')
+    ...     print 'server connection sending back response: %s' % data
+    ...     yield until_sent(data + '\\r\\n')
+
+    >>> server = AsyncChatCoroutine(server_coroutine())
+    server now listening.
+    server now spawning client.
+    client now connecting to server.
+    server now accepting connections.
+
+    >>> loop()
+    server now spawning connection.
+    server connection waiting for request.
+    client now connected, sending text.
+    client waiting for response.
+    server connection sending back response: hai2u
+    client received response: hai2u
+
+'''
+
 import sys
 import socket
 import asyncore
@@ -16,7 +61,7 @@
 
 def loop(timeout = DEFAULT_LOOP_TIMEOUT):
     start_time = time.time()
-    while 1:
+    while asyncore.socket_map or time_map:
         asyncore.loop(timeout = timeout, count = 1)
         curr_time = time.time()
         time_elapsed = curr_time - start_time
@@ -54,16 +99,20 @@
     def get_formatted_coroutine_traceback(self):
         if not self.__coroutine:
             return ""
-        lines = ['Coroutine traceback (most recent call last):']
+        lines = []
         frames = [coroutine.gi_frame
                   for coroutine in self.__coroutine_stack]
-        frames.append(self.__coroutine.gi_frame)
+        if self.__coroutine.gi_frame:
+            frames.append(self.__coroutine.gi_frame)
         for frame in frames:
             name = frame.f_code.co_name
             filename = frame.f_code.co_filename
             lineno = frame.f_lineno
             lines.append('File "%s", line %d, in coroutine %s' %
                           (filename, lineno, name))
+        if not lines:
+            return 'No coroutine traceback available.'
+        lines.insert(0, 'Coroutine traceback (most recent call last):')
         return '\n'.join(lines)
 
     def close_coroutine_stack(self):
@@ -184,14 +233,18 @@
     def handle_timeout(self):
         self.dispatcher.handle_close()
 
-class until_connection_accepted(CoroutineInstruction):
+class until_listening(CoroutineInstruction):
     def do_execute(self, bind_addr):
-        if not self.dispatcher.socket:
-            self.dispatcher.create_socket(socket.AF_INET,
-                                          socket.SOCK_STREAM)
-            self.dispatcher.set_reuse_addr()
-            self.dispatcher.bind(bind_addr)
-            self.dispatcher.listen(1)
+        self.dispatcher.create_socket(socket.AF_INET,
+                                      socket.SOCK_STREAM)
+        self.dispatcher.set_reuse_addr()
+        self.dispatcher.bind(bind_addr)
+        self.dispatcher.listen(1)
+        self.dispatcher.trampoline.continue_from_yield()
+
+class until_connection_accepted(CoroutineInstruction):
+    def do_execute(self):
+        pass
 
     def handle_accept(self):
         data = self.dispatcher.accept()
@@ -199,8 +252,8 @@
 
 class until_connected(CoroutineInstruction):
     def do_execute(self, addr):
-        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
-        self.connect(addr)
+        self.dispatcher.create_socket(socket.AF_INET, socket.SOCK_STREAM)
+        self.dispatcher.connect(addr)
 
     def handle_connect(self):
         self.dispatcher.trampoline.continue_from_yield()
@@ -254,3 +307,8 @@
 class return_value(CoroutineInstruction):
     def do_execute(self, value):
         self.dispatcher.trampoline.close_coroutine_and_return_to_caller(value)
+
+if __name__ == '__main__':
+    import doctest
+
+    doctest.testmod(verbose = True)
--- a/openwebchat.py	Sat May 02 00:47:23 2009 -0700
+++ b/openwebchat.py	Sat May 02 08:13:45 2009 -0700
@@ -125,8 +125,9 @@
             yield until_sent(block)
 
     def _server_coroutine(self, bind_addr):
+        yield until_listening(bind_addr)
         while 1:
-            conn, addr = yield until_connection_accepted(bind_addr)
+            conn, addr = yield until_connection_accepted()
             AsyncChatCoroutine(self._connection_coroutine(addr), conn)
 
     def _connection_coroutine(self, addr):