Rev 57: Test server test passing. in file:///net/bigmamac/Volumes/home/vila/.bazaar/plugins/local_test_server/

Vincent Ladeuil v.ladeuil+lp at free.fr
Mon Feb 23 13:12:19 GMT 2009


At file:///net/bigmamac/Volumes/home/vila/.bazaar/plugins/local_test_server/

------------------------------------------------------------
revno: 57
revision-id: v.ladeuil+lp at free.fr-20090223131218-8nhpac12wk85xfw7
parent: v.ladeuil+lp at free.fr-20090223112714-skdetd3uwoofskri
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: local_test_server
timestamp: Mon 2009-02-23 14:12:18 +0100
message:
  Test server test passing.
  
  * tests/test_utils.py:
  (full_scenarios): Complete muddleftpd definition.
  
  * test_server.py:
  (MuddleftpdFeature, Muddleftpd): New classes.
  (get_test_permutations): Add muddleftpd permutation.
  
  * server.py:
  (Server._kill_server): Add docstring, return True if zombie
  catched.
  (Muddleftpd.is_installed): We need ftpwho too.
  (Muddleftpd.get_pid): 'ftpwho -p' is the reliable way to get the
  pid.
  (Muddleftpd._start): Use get_pid() to ensure the server was started.
  (Muddleftpd._stop): There is no pidfile.
  
  * configs/muddleftpd.conf:
  (scratchfile): Mention that this more or less implies that we run
  a single server only.
-------------- next part --------------
=== modified file 'configs/muddleftpd.conf'
--- a/configs/muddleftpd.conf	2009-02-23 11:27:14 +0000
+++ b/configs/muddleftpd.conf	2009-02-23 13:12:18 +0000
@@ -9,6 +9,8 @@
 maxusers 100
 timeout 300
 logfile %(log_file)s
+# We may need to uniquify the path below if we want multiple
+# servers. Use port ?
 scratchfile %(var_lock_dir)s/muddleftpd.scratch
 
 # log everything except debugging logs

=== modified file 'server.py'
--- a/server.py	2009-02-23 11:27:14 +0000
+++ b/server.py	2009-02-23 13:12:18 +0000
@@ -282,6 +282,10 @@
         return self._hk_poll(self.is_running)
 
     def _kill_server(self, pid, sig):
+        """Kill the server running as pid with sig.
+
+        :returns: True if the process doesn't exist anymore, False otherwise.
+        """
         try:
             os.kill(pid, sig)
         except OSError, e:
@@ -296,7 +300,7 @@
         except OSError, e:
             if e.errno == errno.ECHILD:
                 # The process doesn't exist anymore
-                pass
+                return True
             else:
                 raise
         return False
@@ -698,6 +702,7 @@
 class Muddleftpd(Server):
 
     _server_command_name = 'muddleftpd'
+    _ftpwho_command_name = 'ftpwho'
 
     def __init__(self, port, _conf=None):
         if _conf is None:
@@ -706,30 +711,40 @@
         super(Muddleftpd, self).__init__(_conf, port)
         self.output_config_path = self.config.abspath('etc/muddleftpd.conf')
 
+    def is_installed(self):
+        return (super(Muddleftpd, self).is_installed
+                and locate_program(self._ftpwho_command_name) is not None)
+
+    def get_pid(self):
+        # muddleftpd doesn't honor the pidfile directive. The 'ftpwho -p'
+        # command has to be used instead.
+        proc = subprocess.Popen([self._ftpwho_command_name, '-p',
+                                 '-c', self.output_config_path],
+                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        stdout, stderr = proc.communicate()
+        try:
+            pid = int(stdout)
+        except ValueError:
+            pid = None
+        return pid
+
     def _start(self):
-        # This is the best we can do: just spawn the process hoping nothing
-        # goes wrong during server launch...
-
-        # NOTE: muddleftpd uses a strange policy, the pidfile is not supported
-        # (it was in the past). Instead a scratchfile is used to synchronize
-        # communications between the various processes involved (muddleftpd,
-        # ftpwho). This sounds too complicated to respect, so we just spawn the
-        # server and handle the pidfile ourselve.
         proc = subprocess.Popen([self._server_command_name,
                                  '-c', self.output_config_path])
-        if proc.returncode is not None:
-            raise LTSCantStartError(self, 'return code: %s' % proc.returncode)
-        f = open(self.get_config_value('pid_file'), 'w')
-        try:
-            f.write('%s' % proc.pid)
-        finally:
-            f.close()
+        # The server is spawned as a child, so we wait for the command to
+        # terminate to be able to check the pid with 'ftpwho -p'
+        stdout, stderr = proc.communicate()
+        if ((proc.returncode is not None
+            and proc.returncode != 0)
+            or self.get_pid() is None):
+            # If we get no pid back, something went wrong
+            raise LTSCantStartError(
+                self, 'return code: %s, stdout: [%r], stderr: [%r]'
+                % (proc.returncode, stdout, stderr))
 
     def _stop(self):
         if not self._wait_for_server_process_death():
             raise LTSCantStopError(self)
-        # We need to delete the pid file ourselves
-        osutils.delete_any(self.get_config_value('pid_file'))
 
 
 # For self tests we use a range of unassigned port numbers as described

=== modified file 'test_server.py'
--- a/test_server.py	2009-02-20 15:57:48 +0000
+++ b/test_server.py	2009-02-23 13:12:18 +0000
@@ -115,6 +115,11 @@
     _server_name = 'proftpd'
 
 
+class MuddleftpdFeature(LocalTestServerFeature):
+
+    _server_name = 'muddleftpd'
+
+
 class LocalTestServer(transport.Server):
 
     # Must be set by daughter classes
@@ -321,7 +326,7 @@
                                           self.host, self.port)
     def get_url(self):
         """See bzrlib.transport.Server.get_url."""
-        # Remote the leading /tmp
+        # Remove the leading /tmp
         prefix = '/tmp/'
         if not self._test_working_dir.startswith(prefix):
             raise AssertionError('%s must start with %s'
@@ -329,6 +334,20 @@
         return self._base_url + self._test_working_dir[len(prefix):]
 
 
+class Muddleftpd(LocalFTPTestServer):
+
+    _server_name = 'muddleftpd'
+
+    def _build_base_url(self):
+        # We use anonymous to avoid having to store the password of the user
+        # running the tests
+        return '%s://anonymous@%s:%s' % (self._url_protocol,
+                                          self.host, self.port)
+    def get_url(self):
+        """See bzrlib.transport.Server.get_url."""
+        return self._base_url + self._test_working_dir
+
+
 # We have registered a transport for the purpose of adding new servers in the
 # test permutations. Registering a transport makes our module appears in the
 # list which is queried for a get_test_permutations function.
@@ -393,4 +412,7 @@
     if ProftpdFeature().available():
         permutations.append((FtpTransport, Proftpd))
 
+    if MuddleftpdFeature().available():
+        permutations.append((FtpTransport, Muddleftpd))
+
     return permutations

=== modified file 'tests/test_utils.py'
--- a/tests/test_utils.py	2009-02-23 11:27:14 +0000
+++ b/tests/test_utils.py	2009-02-23 13:12:18 +0000
@@ -171,8 +171,8 @@
                 _server_name='muddleftpd',
                 _config_class=config.Muddleftpd,
                 _server_class=server.Muddleftpd,
-#                _server_feature_class=test_server.MuddleftpdFeature,
-#                    _test_server_class=test_server.Muddleftpd,
+                _server_feature_class=test_server.MuddleftpdFeature,
+                _test_server_class=test_server.Muddleftpd,
                 )),
         ]
     return scenarios



More information about the bazaar-commits mailing list