Rev 8: Create a dedicated hierarchy by server at start time. Use test ports for in file:///v/home/vila/.bazaar/plugins/local_test_server/
Vincent Ladeuil
v.ladeuil+lp at free.fr
Wed May 28 20:10:59 BST 2008
At file:///v/home/vila/.bazaar/plugins/local_test_server/
------------------------------------------------------------
revno: 8
revision-id: v.ladeuil+lp at free.fr-20080528191059-gq4r5s90t7y3lm93
parent: v.ladeuil+lp at free.fr-20080528111938-d0spqs2co7r2m03c
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: local_test_server
timestamp: Wed 2008-05-28 21:10:59 +0200
message:
Create a dedicated hierarchy by server at start time. Use test ports for
tests.
* tests/test_server.py:
(TestServer): Define a base class with some helpers.
* tests/test_config.py:
(TestConfig): Define a base class with some helpers.
(TestBaseConfig.test_ensure_required_dirs_exist): New test.
(TestBaseConfig.test_config_defines_keywords): Simplified.
(TestBaseConfig.test_expand_keywords): Simplified.
(TestConfigApache2.test_config_defines_keywords): New test.
* server.py:
(Apache2.__init__): Add a _conf parameter for tests.
(Apache2.start): Ensures required dirs exist before opening output
file.
(Apache2.stop): Use the correct generated configuration file.
* configs/apache2.conf:
Reference host and port.
* config.py:
(Config.__init__): Add required_dirs and _base_dir
parameters. Calculate paths.
(Config.abspath): New method.
(Config.ensure_required_dirs_exist): New method.
(Apache2): Declare specific required subdirs.
removed:
etc/ etc-20080523170706-tosxlttyvwvutu4s-1
var/ var-20080523170708-nkpjg07oorui519n-1
var/lock/ lock-20080523170716-vl523z7to322eg8a-1
var/run/ run-20080523170717-jvc42ynv6ghppmnk-1
modified:
TODO todo-20080526134120-eibvvebw74t8j2xh-1
commands.py commands.py-20080524160638-76gsirgigzamza15-1
config.py __init__.py-20080523170713-0c8mnxio9r41iyhk-1
configs/apache2.conf apache2.conf-20080522095851-6eixwo2qv9brec67-1
server.py server.py-20080524160639-rqhbexqatjqbwypw-1
tests/test_config.py test_config.py-20080523170715-clr6vz0qdzefftob-1
tests/test_server.py test_server.py-20080524160641-lco15o23ub9mac33-1
-------------- next part --------------
=== modified file 'TODO'
--- a/TODO 2008-05-28 10:57:57 +0000
+++ b/TODO 2008-05-28 19:10:59 +0000
@@ -1,13 +1,5 @@
* server.py
-- 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
+* plug the server if the corresponding feature is available.
=== modified file 'commands.py'
--- a/commands.py 2008-05-28 08:27:12 +0000
+++ b/commands.py 2008-05-28 19:10:59 +0000
@@ -36,7 +36,7 @@
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))
+ % (name, s.get_pid(), s.port))
class cmd_lts_stop(bzrlib.commands.Command):
=== modified file 'config.py'
--- a/config.py 2008-05-28 11:19:38 +0000
+++ b/config.py 2008-05-28 19:10:59 +0000
@@ -14,7 +14,11 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-"""configs -- provides access to server configurations."""
+"""configs -- generates server configurations."""
+
+import errno
+import os
+
from bzrlib import (
osutils,
@@ -30,50 +34,76 @@
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
-configs_dir = get_lts_path('configs')
-
-
class Config(object):
- def __init__(self, name):
+ def __init__(self, name, required_dirs=None, _base_dir=None):
+ """Constructor.
+
+ :param name: The name of the server, also used to build various dirs.
+ :param required_dirs: A dict where keys are the name to use in config
+ files and values the path relative to server work directory.
+ :param _base_dir: An alternate base directory to use instead of the
+ default 'work'
+
+ Each server gets its own directory under the 'work/<server_name>'
+ subdir of the plugin. This helps administration and debugging by
+ grouping all server files in the same place.
+ """
self.name = name
+ if _base_dir is None:
+ _base_dir = get_lts_path('work/%s' % name)
+ self.base_dir = _base_dir
self.values = dict(server_name=name,
- 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,
# Will be updated at server creation
host='example.com' ,port=0,
- )
+ )
+ # We need at least a place to put the generated configuration file and
+ # the pidfile.
+ self.required_dirs = dict(etc_dir='etc', var_run_dir='var/run')
+ if required_dirs is not None:
+ self.required_dirs.update(required_dirs)
+
+ for name, relpath in self.required_dirs.items():
+ self.values[name] = self.abspath(relpath)
+
+ self.values['base_dir'] = self.base_dir
+ self.values['pid_file'] = self.abspath('var/run/%s.pid' % self.name)
+
+ def abspath(self, relpath=None):
+ return osutils.pathjoin(self.base_dir, relpath)
def expand(self, infile, outfile):
"""Expand all the config keywords.
- :param infile: A file containing the kwywords to be expanded
+ :param infile: A file containing the keywords to be expanded
:param outfile: A opened file where the expansion result is written
"""
for line in infile.readlines():
outfile.write(line % self.values)
+ def ensure_required_dirs_exist(self):
+ for dir in self.required_dirs.keys():
+ try:
+ os.makedirs(self.get_value(dir))
+ except OSError, e:
+ if e.errno == errno.EEXIST:
+ # Better ask for forgiveness
+ pass
+ else:
+ raise
+
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)
+ _required_dirs = dict(var_lock_dir='var/lock',
+ var_log_dir='var/log')
+
+
+ def __init__(self, _base_dir=None):
+ super(Apache2, self).__init__('apache2',
+ required_dirs=self._required_dirs,
+ _base_dir=_base_dir)
self.config_path = get_lts_path('configs/apache2.conf')
=== modified file 'configs/apache2.conf'
--- a/configs/apache2.conf 2008-05-26 19:42:08 +0000
+++ b/configs/apache2.conf 2008-05-28 19:10:59 +0000
@@ -9,7 +9,7 @@
# root. We want directories writable by the user running the
# tests.
-ServerRoot "%(root_dir)s"
+ServerRoot "%(base_dir)s"
LockFile "%(var_lock_dir)s/accept.lock
@@ -43,12 +43,10 @@
#
KeepAliveTimeout 5
-ErrorLog %(var_log_dir)s/apache2/error.log
-LogLevel warn
-CustomLog %(var_log_dir)s/apache2/access.log combined
+ErrorLog %(var_log_dir)s/error.log
-ServerName localhost
-Listen 8080
+ServerName %(host)s
+Listen %(port)s
# The following directives seems to activate the smallest apache2
# server possible. If you know better, comments are very welcome.
=== removed directory 'etc'
=== modified file 'server.py'
--- a/server.py 2008-05-28 11:19:38 +0000
+++ b/server.py 2008-05-28 19:10:59 +0000
@@ -32,11 +32,11 @@
def __init__(self, config, port=-1):
self.host = 'localhost'
- if port != -1:
- self.port = port
- else:
+ if port == -1:
# For tests only
self.port = _get_available_port()
+ else:
+ self.port = port
config.values.update(host=self.host, port=self.port)
self.config = config
@@ -79,26 +79,32 @@
# alternative
_hk_interval = 10.0 # in miliseconds
- def __init__(self, port):
- super(Apache2, self).__init__(config.Apache2(), port)
+ def __init__(self, port, _conf=None):
+ if _conf is None:
+ _conf = config.Apache2()
+ super(Apache2, self).__init__(_conf, port)
def start(self):
infile = open(self.config.config_path)
- config_filename = config.get_lts_path('etc/apache2.conf')
+ config_filename = self.config.abspath('etc/apache2.conf')
+ self.config.ensure_required_dirs_exist()
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 ])
+ try:
+ subprocess.check_call(['apache2', '-k', 'start',
+ '-f', config_filename ])
+ except subprocess.CalledProcessError, e:
+ raise errors.BzrCommandError('apache2 cannot be started')
if not self._wait_for_pidfile_to_be_created():
- raise errors.BzrCommandError('apache2 cannot be atarted')
+ raise errors.BzrCommandError('apache2 pidfile not created')
def stop(self):
- config_filename = config.get_lts_path('etc/apache2.conf')
+ config_filename = self.config.abspath('etc/apache2.conf')
pid = self.get_pid()
# Tell it to stop
subprocess.call(['apache2', '-k', 'stop',
=== modified file 'tests/test_config.py'
--- a/tests/test_config.py 2008-05-28 11:19:38 +0000
+++ b/tests/test_config.py 2008-05-28 19:10:59 +0000
@@ -19,6 +19,7 @@
from cStringIO import StringIO
from bzrlib import (
+ osutils,
tests,
)
@@ -29,44 +30,42 @@
)
-class TestConfigEnv(tests.TestCase):
-
- def test_etc_exists(self):
- self.failUnlessExists(config.etc_dir)
-
- def test_var_exists(self):
- 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):
+class TestConfig(tests.TestCaseInTempDir):
+
+ def _get_config(self, klass, *args, **kwargs):
+ kwargs['_base_dir'] = self.test_dir
+ return klass(*args,**kwargs)
+
+ def _abspath(self, relpath):
+ return osutils.pathjoin(self.test_dir, relpath)
+
+ def _check_conf_path(self, conf, name, expected_path):
+ self.assertEqual(self._abspath(expected_path), conf.get_value(name))
+
+
+class TestBaseConfig(TestConfig):
+
+ def test_lts_path(self):
path = config.get_lts_path('configs/foo')
self.assertTrue(path.endswith('local_test_server/configs/foo'))
path = config.get_lts_path('var/run/foo')
self.assertTrue(path.endswith('local_test_server/var/run/foo'))
+ def test_ensure_required_dirs_exist(self):
+ req_dirs = dict(bar='bar', baz='baz')
+ c = self._get_config(config.Config, 'foo', req_dirs)
+ c.ensure_required_dirs_exist()
+ self.failUnlessExists(self._abspath('bar'))
+ self.failUnlessExists(self._abspath('baz'))
def test_config_defines_keywords(self):
- conf = config.Config('foo')
+ conf = self._get_config(config.Config, 'foo')
self.assertEquals('foo', conf.values.get('server_name'))
- 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'))
+ self._check_conf_path(conf, 'etc_dir', 'etc')
+ self._check_conf_path(conf, 'var_run_dir', 'var/run')
def test_expand_no_keywords(self):
- conf = config.Config('foo')
+ conf = self._get_config(config.Config, 'foo')
content = 'nearly_empty'
inf = StringIO(content)
outf = StringIO()
@@ -74,14 +73,12 @@
self.assertEqual(content, outf.getvalue())
def test_expand_keywords(self):
- conf = config.Config('foo')
+ conf = self._get_config(config.Config, 'foo')
content = '''
my name is %(server_name)s
my address is %(host)s:%(port)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()
@@ -93,15 +90,14 @@
expanded, 'my config is generated under .*/etc\n')
self.assertContainsRe(
expanded, 'my pid is somewhere below .*/var/run\n')
- self.assertContainsRe(
- 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'))
+
+
+class TestConfigApache2(TestConfig):
+
+ def test_config_defines_keywords(self):
+ conf = self._get_config(config.Apache2)
+ self.assertEquals('apache2', conf.get_value('server_name'))
+ self._check_conf_path(conf, 'etc_dir', 'etc')
+ self._check_conf_path(conf, 'var_run_dir', 'var/run')
+ self._check_conf_path(conf, 'var_lock_dir', 'var/lock')
+ self._check_conf_path(conf, 'var_log_dir', 'var/log')
=== modified file 'tests/test_server.py'
--- a/tests/test_server.py 2008-05-28 10:57:57 +0000
+++ b/tests/test_server.py 2008-05-28 19:10:59 +0000
@@ -24,6 +24,7 @@
from bzrlib.plugins.local_test_server import (
+ config,
server,
)
@@ -51,20 +52,34 @@
self.assertRaises(ValueError, server._get_available_port)
-class TestApache2(tests.TestCase):
+class TestServer(tests.TestCaseInTempDir):
+
+ def _get_config(self, klass, *args, **kwargs):
+ kwargs['_base_dir'] = self.test_dir
+ return klass(*args,**kwargs)
+
+ def _get_server(self, klass, config):
+ return klass(server._get_available_port(), config)
+
+
+class TestApache2(TestServer):
+
+ def _get_server(self):
+ conf = self._get_config(config.Apache2)
+ return super(TestApache2, self)._get_server(server.Apache2, conf)
def test_server_doesn_t_run(self):
- s = server.get_server('apache2')
+ s = self._get_server()
self.assertFalse(s.is_running())
def test_server_start(self):
- s = server.get_server('apache2')
+ s = self._get_server()
s.start()
self.addCleanup(s.stop)
self.assertTrue(s.is_running())
def test_server_stop(self):
- s = server.get_server('apache2')
+ s = self._get_server()
s.start()
self.assertTrue(s.is_running())
s.stop()
=== removed directory 'var'
=== removed directory 'var/lock'
=== removed directory 'var/run'
More information about the bazaar-commits
mailing list