tests for wsgi/daemon config parsing

Change-Id: Ibb82555830b88962cc765fc88281ca42a9ce9d9c
This commit is contained in:
Clay Gerrard 2023-04-04 15:42:36 -05:00
parent 8e875df65a
commit c95f8e6c05
4 changed files with 226 additions and 7 deletions

View File

@ -315,7 +315,9 @@ def run_daemon(klass, conf_file, section_name='', once=False, **kwargs):
logger.notice('Starting %s', os.getpid())
try:
DaemonStrategy(klass(conf), logger).run(once=once, **kwargs)
d = klass(conf)
DaemonStrategy(d, logger).run(once=once, **kwargs)
except KeyboardInterrupt:
logger.info('User quit')
logger.notice('Exited %s', os.getpid())
return d

View File

@ -1408,3 +1408,36 @@ def generate_db_path(tempdir, server_type):
return os.path.join(
tempdir, '%ss' % server_type, 'part', 'suffix', 'hash',
'%s-%s.db' % (server_type, uuid4()))
class ConfigAssertMixin(object):
"""
Use this with a TestCase to get py2/3 compatible assert for DuplicateOption
"""
def assertDuplicateOption(self, app_config, option_name, option_value):
"""
PY3 added a DuplicateOptionError, PY2 didn't seem to care
"""
if six.PY3:
self.assertDuplicateOptionError(app_config, option_name)
else:
self.assertDuplicateOptionOK(app_config, option_name, option_value)
def assertDuplicateOptionError(self, app_config, option_name):
with self.assertRaises(
utils.configparser.DuplicateOptionError) as ctx:
app_config()
msg = str(ctx.exception)
self.assertIn(option_name, msg)
self.assertIn('already exists', msg)
def assertDuplicateOptionOK(self, app_config, option_name, option_value):
app = app_config()
if hasattr(app, 'conf'):
found_value = app.conf[option_name]
else:
if hasattr(app, '_pipeline_final_app'):
# special case for proxy app!
app = app._pipeline_final_app
found_value = getattr(app, option_name)
self.assertEqual(found_value, option_value)

View File

@ -14,18 +14,19 @@
# limitations under the License.
import os
from six import StringIO
import six
import time
import unittest
from getpass import getuser
import logging
from test.unit import tmpfile
from test.unit import tmpfile, with_tempdir, ConfigAssertMixin
import mock
import signal
from contextlib import contextmanager
import itertools
from collections import defaultdict
import errno
from textwrap import dedent
from swift.common import daemon, utils
from test.debug_logger import debug_logger
@ -106,7 +107,7 @@ class TestWorkerDaemon(unittest.TestCase):
self.assertTrue(d.is_healthy())
class TestRunDaemon(unittest.TestCase):
class TestRunDaemon(unittest.TestCase, ConfigAssertMixin):
def setUp(self):
for patcher in [
@ -167,7 +168,7 @@ class TestRunDaemon(unittest.TestCase):
conf_file, once=True)
# test user quit
sio = StringIO()
sio = six.StringIO()
logger = logging.getLogger('server')
logger.addHandler(logging.StreamHandler(sio))
logger = utils.get_logger(None, 'server', log_route='server')
@ -207,6 +208,91 @@ class TestRunDaemon(unittest.TestCase):
os.environ['TZ'] = old_tz
time.tzset()
@with_tempdir
def test_run_deamon_from_conf_file(self, tempdir):
conf_path = os.path.join(tempdir, 'test-daemon.conf')
conf_body = """
[DEFAULT]
conn_timeout = 5
client_timeout = 1
[my-daemon]
CONN_timeout = 10
client_timeout = 2
"""
contents = dedent(conf_body)
with open(conf_path, 'w') as f:
f.write(contents)
with mock.patch('swift.common.daemon.use_hub'):
d = daemon.run_daemon(MyDaemon, conf_path)
# my-daemon section takes priority (!?)
self.assertEqual('2', d.conf['client_timeout'])
self.assertEqual('10', d.conf['conn_timeout'])
@with_tempdir
def test_run_daemon_from_conf_file_with_duplicate_var(self, tempdir):
conf_path = os.path.join(tempdir, 'test-daemon.conf')
conf_body = """
[DEFAULT]
client_timeout = 3
[my-daemon]
CLIENT_TIMEOUT = 2
client_timeout = 1
"""
contents = dedent(conf_body)
with open(conf_path, 'w') as f:
f.write(contents)
with mock.patch('swift.common.daemon.use_hub'):
app_config = lambda: daemon.run_daemon(MyDaemon, tempdir)
self.assertDuplicateOption(app_config, 'client_timeout', '1')
@with_tempdir
def test_run_deamon_from_conf_dir(self, tempdir):
conf_files = {
'default': """
[DEFAULT]
conn_timeout = 5
client_timeout = 1
""",
'daemon': """
[DEFAULT]
CONN_timeout = 3
CLIENT_TIMEOUT = 4
[my-daemon]
CONN_timeout = 10
client_timeout = 2
""",
}
for filename, conf_body in conf_files.items():
path = os.path.join(tempdir, filename + '.conf')
with open(path, 'wt') as fd:
fd.write(dedent(conf_body))
with mock.patch('swift.common.daemon.use_hub'):
d = daemon.run_daemon(MyDaemon, tempdir)
# my-daemon section takes priority (!?)
self.assertEqual('2', d.conf['client_timeout'])
self.assertEqual('10', d.conf['conn_timeout'])
@with_tempdir
def test_run_daemon_from_conf_dir_with_duplicate_var(self, tempdir):
conf_files = {
'default': """
[DEFAULT]
client_timeout = 3
""",
'daemon': """
[my-daemon]
client_timeout = 2
CLIENT_TIMEOUT = 4
""",
}
for filename, conf_body in conf_files.items():
path = os.path.join(tempdir, filename + '.conf')
with open(path, 'wt') as fd:
fd.write(dedent(conf_body))
with mock.patch('swift.common.daemon.use_hub'):
app_config = lambda: daemon.run_daemon(MyDaemon, tempdir)
self.assertDuplicateOption(app_config, 'client_timeout', '4')
@contextmanager
def mock_os(self, child_worker_cycles=3):
self.waitpid_calls = defaultdict(int)

View File

@ -43,7 +43,7 @@ from swift.common.storage_policy import POLICIES
from test import listen_zero
from test.debug_logger import debug_logger
from test.unit import (
temptree, with_tempdir, write_fake_ring, patch_policies)
temptree, with_tempdir, write_fake_ring, patch_policies, ConfigAssertMixin)
from paste.deploy import loadwsgi
@ -60,7 +60,7 @@ def _fake_rings(tmpdir):
@patch_policies
class TestWSGI(unittest.TestCase):
class TestWSGI(unittest.TestCase, ConfigAssertMixin):
"""Tests for swift.common.wsgi"""
def test_init_request_processor(self):
@ -133,14 +133,38 @@ class TestWSGI(unittest.TestCase):
def test_loadapp_from_file(self, tempdir):
conf_path = os.path.join(tempdir, 'object-server.conf')
conf_body = """
[DEFAULT]
CONN_timeout = 10
client_timeout = 1
[app:main]
use = egg:swift#object
conn_timeout = 5
client_timeout = 2
CLIENT_TIMEOUT = 3
"""
contents = dedent(conf_body)
with open(conf_path, 'w') as f:
f.write(contents)
app = wsgi.loadapp(conf_path)
self.assertIsInstance(app, obj_server.ObjectController)
self.assertTrue(isinstance(app, obj_server.ObjectController))
self.assertEqual(1, app.client_timeout)
self.assertEqual(5, app.conn_timeout)
@with_tempdir
def test_loadapp_from_file_with_duplicate_var(self, tempdir):
conf_path = os.path.join(tempdir, 'object-server.conf')
conf_body = """
[app:main]
use = egg:swift#object
client_timeout = 2
client_timeout = 3
"""
contents = dedent(conf_body)
with open(conf_path, 'w') as f:
f.write(contents)
app_config = lambda: wsgi.loadapp(conf_path)
self.assertDuplicateOption(app_config, 'client_timeout', 3.0)
@with_tempdir
def test_loadapp_from_file_with_global_conf(self, tempdir):
@ -204,11 +228,85 @@ class TestWSGI(unittest.TestCase):
def test_loadapp_from_string(self):
conf_body = """
[DEFAULT]
CONN_timeout = 10
client_timeout = 1
[app:main]
use = egg:swift#object
conn_timeout = 5
client_timeout = 2
"""
app = wsgi.loadapp(wsgi.ConfigString(conf_body))
self.assertTrue(isinstance(app, obj_server.ObjectController))
self.assertEqual(1, app.client_timeout)
self.assertEqual(5, app.conn_timeout)
@with_tempdir
def test_loadapp_from_dir(self, tempdir):
conf_files = {
'pipeline': """
[pipeline:main]
pipeline = tempauth proxy-server
""",
'tempauth': """
[DEFAULT]
swift_dir = %s
random_VAR = foo
[filter:tempauth]
use = egg:swift#tempauth
random_var = bar
""" % tempdir,
'proxy': """
[DEFAULT]
conn_timeout = 5
client_timeout = 1
[app:proxy-server]
use = egg:swift#proxy
CONN_timeout = 10
client_timeout = 2
""",
}
_fake_rings(tempdir)
for filename, conf_body in conf_files.items():
path = os.path.join(tempdir, filename + '.conf')
with open(path, 'wt') as fd:
fd.write(dedent(conf_body))
app = wsgi.loadapp(tempdir)
# DEFAULT takes priority (!?)
self.assertEqual(5, app._pipeline_final_app.conn_timeout)
self.assertEqual(1, app._pipeline_final_app.client_timeout)
self.assertEqual('foo', app.app.app.app.conf['random_VAR'])
self.assertEqual('bar', app.app.app.app.conf['random_var'])
@with_tempdir
def test_loadapp_from_dir_with_duplicate_var(self, tempdir):
conf_files = {
'pipeline': """
[pipeline:main]
pipeline = tempauth proxy-server
""",
'tempauth': """
[DEFAULT]
swift_dir = %s
random_VAR = foo
[filter:tempauth]
use = egg:swift#tempauth
random_var = bar
""" % tempdir,
'proxy': """
[app:proxy-server]
use = egg:swift#proxy
client_timeout = 2
CLIENT_TIMEOUT = 1
""",
}
_fake_rings(tempdir)
for filename, conf_body in conf_files.items():
path = os.path.join(tempdir, filename + '.conf')
with open(path, 'wt') as fd:
fd.write(dedent(conf_body))
app_config = lambda: wsgi.loadapp(tempdir)
self.assertDuplicateOption(app_config, 'client_timeout', 2.0)
@with_tempdir
def test_load_app_config(self, tempdir):