Rev 3: Diry commit. This is not going as it should *at all*. But it kinda works. in file:///v/home/vila/.bazaar/plugins/local_test_server/
Vincent Ladeuil
v.ladeuil+lp at free.fr
Mon May 26 20:42:08 BST 2008
At file:///v/home/vila/.bazaar/plugins/local_test_server/
------------------------------------------------------------
revno: 3
revision-id: v.ladeuil+lp at free.fr-20080526194208-9eqqggi0hi421yg0
parent: v.ladeuil+lp at free.fr-20080523171036-0oimydn77kxknddm
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: local_test_server
timestamp: Mon 2008-05-26 21:42:08 +0200
message:
Diry commit. This is not going as it should *at all*. But it kinda works.
added:
TODO todo-20080526134120-eibvvebw74t8j2xh-1
commands.py commands.py-20080524160638-76gsirgigzamza15-1
server.py server.py-20080524160639-rqhbexqatjqbwypw-1
tests/test_commands.py test_commands.py-20080524160640-bfduau8g3hsg83sa-1
tests/test_server.py test_server.py-20080524160641-lco15o23ub9mac33-1
renamed:
configs/__init__.py => config.py __init__.py-20080523170713-0c8mnxio9r41iyhk-1
modified:
__init__.py __init__.py-20080521133755-h9wimitytocyyxyv-1
configs/apache2.conf apache2.conf-20080522095851-6eixwo2qv9brec67-1
tests/__init__.py __init__.py-20080522095852-86lozt5jrpmajiqg-1
tests/test_config.py test_config.py-20080523170715-clr6vz0qdzefftob-1
config.py __init__.py-20080523170713-0c8mnxio9r41iyhk-1
-------------- next part --------------
=== added file 'TODO'
--- a/TODO 1970-01-01 00:00:00 +0000
+++ b/TODO 2008-05-26 19:42:08 +0000
@@ -0,0 +1,15 @@
+* server.py
+
+- test stop
+
+- create a hierarchy by server at start time (making more obvious
+ what server is used and the requirements for each server)
+
+- make port a constructor parameter
+
+- make tests use different ports or the servers will not be
+ usable during selftest (doh !).
+
+* create a bzrlib.tests.Feature by server
+
+* plug the server if the corresponding feature is available.
\ No newline at end of file
=== modified file '__init__.py'
--- a/__init__.py 2008-05-23 17:10:36 +0000
+++ b/__init__.py 2008-05-26 19:42:08 +0000
@@ -69,24 +69,8 @@
osutils,
)
-# Directory containing all server configuration files
-base_dir = osutils.dirname(osutils.realpath(__file__))
-
-def get_lts_path(name, subdirs=None, mod=None):
- """Build and return a path in the local_test_server hierarchy."""
- if mod is None:
- mod = osutils.dirname(osutils.realpath(__file__))
- if subdirs is not None:
- mod = osutils.pathjoin(mod, *subdirs)
- return osutils.pathjoin(mod, name)
-
-
-etc_dir = get_lts_path('etc')
-
-# Run-time directories
-var_dir = get_lts_path('var')
-var_run_dir = get_lts_path('run', ['var'])
-var_lock_dir = get_lts_path('lock', ['var'])
+from bzrlib.plugins.local_test_server import commands
+
def load_tests(basic_tests, module, loader):
# This module shouldn't define any tests but I don't know how to report
=== added file 'commands.py'
--- a/commands.py 1970-01-01 00:00:00 +0000
+++ b/commands.py 2008-05-26 19:42:08 +0000
@@ -0,0 +1,60 @@
+# Copyright (C) 2008 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""Commands to manage local test servers."""
+
+
+from bzrlib import (
+ errors,
+ )
+import bzrlib.commands
+
+
+from bzrlib.plugins.local_test_server import (
+ server,
+ )
+
+class cmd_lts_start(bzrlib.commands.Command):
+ """Start a test server."""
+
+ takes_args = ['name']
+
+ @bzrlib.commands.display_command
+ def run(self, name=None):
+ s = server.get_server(name)
+ if server is None:
+ raise errors.BzrCommandError('Server %s is unknown')
+ s.start()
+ self.outf.write('Server %s started with pid %s on port %s\n'
+ % (name, s.pid, s.port))
+
+
+class cmd_lts_stop(bzrlib.commands.Command):
+ """Stop a test server."""
+
+ takes_args = ['name']
+
+ @bzrlib.commands.display_command
+ def run(self, name=None):
+ s = server.get_server(name)
+ if server is None:
+ raise errors.BzrCommandError('Server %s is unknown')
+ s.stop()
+ self.outf.write('Server %s stopped\n' % name)
+
+
+bzrlib.commands.register_command(cmd_lts_start)
+bzrlib.commands.register_command(cmd_lts_stop)
+
=== renamed file 'configs/__init__.py' => 'config.py'
--- a/configs/__init__.py 2008-05-23 17:10:36 +0000
+++ b/config.py 2008-05-26 19:42:08 +0000
@@ -21,11 +21,26 @@
)
-import bzrlib.plugins.local_test_server as lts
+# Base directory containing all other interesting directories
+base_dir = osutils.dirname(osutils.realpath(__file__))
+
+def get_lts_path(relpath):
+ """Build and return a path in the local_test_server hierarchy."""
+ return osutils.pathjoin(osutils.dirname(osutils.realpath(__file__)),
+ relpath)
+
+
+etc_dir = get_lts_path('etc')
+
+# Run-time directories
+var_dir = get_lts_path('var')
+var_run_dir = get_lts_path('var/run')
+var_lock_dir = get_lts_path('var/lock')
+var_log_dir = get_lts_path('var/log')
# Directory containing all server configuration files
-base_dir = lts.get_lts_path('configs')
+configs_dir = get_lts_path('configs')
class Config(object):
@@ -33,10 +48,12 @@
def __init__(self, name):
self.name = name
self.values = dict(server_name=name,
- etc_dir=lts.etc_dir,
- var_dir=lts.var_dir,
- var_run_dir=lts.var_run_dir,
- var_lock_dir=lts.var_lock_dir)
+ root_dir=base_dir,
+ etc_dir=etc_dir,
+ var_dir=var_dir,
+ var_run_dir=var_run_dir,
+ var_lock_dir=var_lock_dir,
+ var_log_dir=var_log_dir)
def expand(self, infile, outfile):
"""Expand all the config keywords.
@@ -46,3 +63,14 @@
"""
for line in infile.readlines():
outfile.write(line % self.values)
+
+ def get_value(self, name, default=None):
+ return self.values.get(name, default)
+
+
+class Apache2(Config):
+
+ def __init__(self):
+ super(Apache2, self).__init__('apache2')
+ self.values['pid_file'] = get_lts_path('var/run/%s.pid' % self.name)
+ self.config_path = get_lts_path('configs/apache2.conf')
=== modified file 'configs/apache2.conf'
--- a/configs/apache2.conf 2008-05-23 17:10:36 +0000
+++ b/configs/apache2.conf 2008-05-26 19:42:08 +0000
@@ -2,14 +2,14 @@
# Based on apache2.conf in ubuntu Gusty
#
-# This file will be processed with python '%' operator see plugin
-# source for details.
+# This file will be interpolated by python see plugin source for
+# details.
# Note that most of the directories below are usually owned by
# root. We want directories writable by the user running the
# tests.
-ServerRoot "%(server_root_dir)s"
+ServerRoot "%(root_dir)s"
LockFile "%(var_lock_dir)s/accept.lock
@@ -43,3 +43,17 @@
#
KeepAliveTimeout 5
+ErrorLog %(var_log_dir)s/apache2/error.log
+LogLevel warn
+CustomLog %(var_log_dir)s/apache2/access.log combined
+
+ServerName localhost
+Listen 8080
+
+# The following directives seems to activate the smallest apache2
+# server possible. If you know better, comments are very welcome.
+# More info at
+# http://localhost/doc/apache2-doc/manual/mod/worker.html
+StartServers 1
+MaxClients 5
+ThreadsPerChild 5
=== added file 'server.py'
--- a/server.py 1970-01-01 00:00:00 +0000
+++ b/server.py 2008-05-26 19:42:08 +0000
@@ -0,0 +1,135 @@
+# Copyright (C) 2008 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+"""The local test servers interfaces."""
+
+import errno
+import subprocess
+import time
+
+
+from bzrlib import (
+ errors,
+ )
+
+
+from bzrlib.plugins.local_test_server import (
+ config,
+ )
+
+
+class Server(object):
+
+ def __init__(self, conf):
+ self.config = conf
+
+ def start(self):
+ raise NotImplementedError(self.start)
+
+ def stop(self):
+ raise NotImplementedError(self.stop)
+
+ def is_running(self):
+ raise NotImplementedError(self.is_running)
+
+ @property
+ def pid(self):
+ raise NotImplementedError(self.pid)
+
+ def get_config_value(self, name, default=None):
+ return self.config.get_value(name, default)
+
+ def _get_file_content(self, relpath):
+ abspath = relpath
+ content = None
+ try:
+ f = open(abspath)
+ except IOError, e:
+ if e.errno == errno.ENOENT:
+ content = None
+ raise errors.NoSuchFile(abspath)
+ else:
+ raise
+ try:
+ content = f.read()
+ finally:
+ f.close()
+ return content
+
+class Apache2(Server):
+
+ def __init__(self):
+ super(Apache2, self).__init__(config.Apache2())
+ self.port = None
+
+ def start(self):
+ infile = open(self.config.config_path)
+ config_filename = config.get_lts_path('etc/apache2.conf')
+ outfile = open(config_filename, 'wt')
+ try:
+ self.config.expand(infile, outfile)
+ finally:
+ infile.close()
+ outfile.close()
+ subprocess.check_call(['apache2', '-k', 'start',
+ '-f', config_filename ])
+ self._wait_for_pidfile_to_be_created()
+
+ def stop(self):
+ config_filename = config.get_lts_path('etc/apache2.conf')
+ retcode = subprocess.check_call(['apache2', '-k', 'stop',
+ '-f', config_filename ])
+
+ def _wait_for_pidfile_to_be_created(self):
+ # I couldn't find a a way/command/parameter to start apache2 to that
+ # pidfile file is created when the command returns. Then, if the server
+ # fails to start no pidfile is ever created. Damn if you wait, damn if
+ # you wait too long ;-)
+ started = False
+ delay = 0.001 # 10 ms
+ # total delay to wait in seconds, if you experienced a longer start
+ # time, well, increase.
+ total_delay = 2
+ for i in range(0, int(total_delay * (1 / delay))):
+ if self.is_running():
+ break
+ else:
+ time.sleep(delay)
+
+ def is_running(self):
+ return bool(self.pid is not None)
+
+ @property
+ def pid(self):
+ try:
+ content = self._get_file_content(self.get_config_value('pid_file'))
+ except errors.NoSuchFile:
+ pid = None
+ else:
+ try:
+ pid = int(content)
+ except (TypeError, ValueError):
+ pid = None
+ return pid
+
+
+_servers = dict(apache2=Apache2)
+
+def get_server(name):
+ klass = _servers.get(name, None)
+ if klass is None:
+ return None
+ else:
+ return klass()
=== modified file 'tests/__init__.py'
--- a/tests/__init__.py 2008-05-23 17:10:36 +0000
+++ b/tests/__init__.py 2008-05-26 19:42:08 +0000
@@ -16,7 +16,9 @@
def load_tests(basic_tests, module, loader):
testmod_names = [
+ 'test_commands',
'test_config',
+ 'test_server',
]
basic_tests.addTest(loader.loadTestsFromModuleNames(
["%s.%s" % (__name__, tmn) for tmn in testmod_names]))
=== added file 'tests/test_commands.py'
--- a/tests/test_commands.py 1970-01-01 00:00:00 +0000
+++ b/tests/test_commands.py 2008-05-26 19:42:08 +0000
@@ -0,0 +1,18 @@
+# Copyright (C) 2008 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""Test the commands to start and stop local test servers."""
+
=== modified file 'tests/test_config.py'
--- a/tests/test_config.py 2008-05-23 17:10:36 +0000
+++ b/tests/test_config.py 2008-05-26 19:42:08 +0000
@@ -25,44 +25,48 @@
import bzrlib.plugins.local_test_server as lts
from bzrlib.plugins.local_test_server import (
- configs
+ config
)
class TestConfigEnv(tests.TestCase):
def test_etc_exists(self):
- self.failUnlessExists(lts.etc_dir)
+ self.failUnlessExists(config.etc_dir)
def test_var_exists(self):
- self.failUnlessExists(lts.var_dir)
-
- def test_var_exists_run(self):
- self.failUnlessExists(lts.var_run_dir)
-
- def test_var_exists_lock(self):
- self.failUnlessExists(lts.var_lock_dir)
+ self.failUnlessExists(config.var_dir)
+
+ def test_var_run_exists(self):
+ self.failUnlessExists(config.var_run_dir)
+
+ def test_var_lock_exists(self):
+ self.failUnlessExists(config.var_lock_dir)
+
+ def test_var_log_exists(self):
+ self.failUnlessExists(config.var_log_dir)
class TestConfig(tests.TestCase):
def test_build_path(self):
- path = lts.get_lts_path('foo', ['configs'])
+ path = config.get_lts_path('configs/foo')
self.assertTrue(path.endswith('local_test_server/configs/foo'))
- path = lts.get_lts_path('foo', ['var', 'run'])
+ path = config.get_lts_path('var/run/foo')
self.assertTrue(path.endswith('local_test_server/var/run/foo'))
def test_config_defines_keywords(self):
- conf = configs.Config('foo')
+ conf = config.Config('foo')
self.assertEquals('foo', conf.values.get('server_name'))
- self.assertEquals(lts.etc_dir, conf.values.get('etc_dir'))
- self.assertEquals(lts.var_dir, conf.values.get('var_dir'))
- self.assertEquals(lts.var_run_dir, conf.values.get('var_run_dir'))
- self.assertEquals(lts.var_lock_dir, conf.values.get('var_lock_dir'))
+ self.assertEquals(config.etc_dir, conf.values.get('etc_dir'))
+ self.assertEquals(config.var_dir, conf.values.get('var_dir'))
+ self.assertEquals(config.var_run_dir, conf.values.get('var_run_dir'))
+ self.assertEquals(config.var_lock_dir, conf.values.get('var_lock_dir'))
+ self.assertEquals(config.var_log_dir, conf.values.get('var_log_dir'))
def test_expand_no_keywords(self):
- conf = configs.Config('foo')
+ conf = config.Config('foo')
content = 'nearly_empty'
inf = StringIO(content)
outf = StringIO()
@@ -70,12 +74,13 @@
self.assertEqual(content, outf.getvalue())
def test_expand_keywords(self):
- conf = configs.Config('foo')
+ conf = config.Config('foo')
content = '''
my name is %(server_name)s
my config is generated under %(etc_dir)s
my pid is somewhere below %(var_run_dir)s
I use some lock mechanism which needs something under %(var_lock_dir)s
+My log files will be under %(var_log_dir)s
'''
inf = StringIO(content)
outf = StringIO()
@@ -90,3 +95,11 @@
expanded, 'I use some lock mechanism which needs something under'
' .*var/lock\n')
+ self.assertContainsRe(
+ expanded, 'My log files will be under .*var/log\n')
+
+
+class TestConfigEnvApache2(tests.TestCase):
+
+ def test_var_log_apache2_exists(self):
+ self.failUnlessExists(config.get_lts_path('var/log/apache2'))
=== added file 'tests/test_server.py'
--- a/tests/test_server.py 1970-01-01 00:00:00 +0000
+++ b/tests/test_server.py 2008-05-26 19:42:08 +0000
@@ -0,0 +1,46 @@
+# Copyright (C) 2008 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""Test local test server interfaces."""
+
+
+from bzrlib import (
+ errors,
+ tests,
+ )
+
+from bzrlib.plugins.local_test_server import (
+ server,
+ )
+
+class TestApache2(tests.TestCase):
+
+ def test_server_doesn_t_run(self):
+ s = server.get_server('apache2')
+ self.assertFalse(s.is_running())
+
+ def test_server_start(self):
+ s = server.get_server('apache2')
+ s.start()
+ self.addCleanup(s.stop)
+ self.assertTrue(s.is_running())
+
+ def test_server_stop(self):
+ s = server.get_server('apache2')
+ s.start()
+ self.assertTrue(s.is_running())
+ s.stop()
+ self.assertFalse(s.is_running())
More information about the bazaar-commits
mailing list