mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-01-11 07:23:04 +00:00
Add everything and nothing config validation helpers
This commit is contained in:
parent
aedac9d570
commit
34714d5f6b
@ -14,6 +14,17 @@ if PY2:
|
|||||||
from builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, list, object, range, str, max, min # noqa: F401
|
from builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, list, object, range, str, max, min # noqa: F401
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
|
from configparser import (
|
||||||
|
ConfigParser,
|
||||||
|
)
|
||||||
|
|
||||||
|
from hypothesis import (
|
||||||
|
given,
|
||||||
|
)
|
||||||
|
from hypothesis.strategies import (
|
||||||
|
dictionaries,
|
||||||
|
text,
|
||||||
|
)
|
||||||
|
|
||||||
from twisted.python.filepath import (
|
from twisted.python.filepath import (
|
||||||
FilePath,
|
FilePath,
|
||||||
@ -23,6 +34,51 @@ from twisted.trial import unittest
|
|||||||
from allmydata.util import configutil
|
from allmydata.util import configutil
|
||||||
|
|
||||||
|
|
||||||
|
def arbitrary_config_dicts(
|
||||||
|
min_sections=0,
|
||||||
|
max_sections=3,
|
||||||
|
max_items_per_section=3,
|
||||||
|
max_item_length=8,
|
||||||
|
max_value_length=8,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Build ``dict[str, dict[str, str]]`` instances populated with arbitrary
|
||||||
|
configurations.
|
||||||
|
"""
|
||||||
|
return dictionaries(
|
||||||
|
text(),
|
||||||
|
dictionaries(
|
||||||
|
text(max_size=max_item_length),
|
||||||
|
text(max_size=max_value_length),
|
||||||
|
max_size=max_items_per_section,
|
||||||
|
),
|
||||||
|
min_size=min_sections,
|
||||||
|
max_size=max_sections,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def to_configparser(dictconfig):
|
||||||
|
"""
|
||||||
|
Take a ``dict[str, dict[str, str]]`` and turn it into the corresponding
|
||||||
|
populated ``ConfigParser`` instance.
|
||||||
|
"""
|
||||||
|
cp = ConfigParser()
|
||||||
|
for section, items in dictconfig.items():
|
||||||
|
cp.add_section(section)
|
||||||
|
for k, v in items.items():
|
||||||
|
cp.set(
|
||||||
|
section,
|
||||||
|
k,
|
||||||
|
# ConfigParser has a feature that everyone knows and loves
|
||||||
|
# where it will use %-style interpolation to substitute
|
||||||
|
# values from one part of the config into another part of
|
||||||
|
# the config. Escape all our `%`s to avoid hitting this
|
||||||
|
# and complicating things.
|
||||||
|
v.replace("%", "%%"),
|
||||||
|
)
|
||||||
|
return cp
|
||||||
|
|
||||||
|
|
||||||
class ConfigUtilTests(unittest.TestCase):
|
class ConfigUtilTests(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(ConfigUtilTests, self).setUp()
|
super(ConfigUtilTests, self).setUp()
|
||||||
@ -166,3 +222,48 @@ enabled = false
|
|||||||
config = configutil.get_config(fname)
|
config = configutil.get_config(fname)
|
||||||
self.assertEqual(config.get("node", "a"), "foo")
|
self.assertEqual(config.get("node", "a"), "foo")
|
||||||
self.assertEqual(config.get("node", "b"), "bar")
|
self.assertEqual(config.get("node", "b"), "bar")
|
||||||
|
|
||||||
|
@given(arbitrary_config_dicts())
|
||||||
|
def test_everything_valid(self, cfgdict):
|
||||||
|
"""
|
||||||
|
``validate_config`` returns ``None`` when the validator is
|
||||||
|
``ValidConfiguration.everything()``.
|
||||||
|
"""
|
||||||
|
cfg = to_configparser(cfgdict)
|
||||||
|
self.assertIs(
|
||||||
|
configutil.validate_config(
|
||||||
|
"<test_everything_valid>",
|
||||||
|
cfg,
|
||||||
|
configutil.ValidConfiguration.everything(),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
|
||||||
|
@given(arbitrary_config_dicts(min_sections=1))
|
||||||
|
def test_nothing_valid(self, cfgdict):
|
||||||
|
"""
|
||||||
|
``validate_config`` raises ``UnknownConfigError`` when the validator is
|
||||||
|
``ValidConfiguration.nothing()`` for all non-empty configurations.
|
||||||
|
"""
|
||||||
|
cfg = to_configparser(cfgdict)
|
||||||
|
with self.assertRaises(configutil.UnknownConfigError):
|
||||||
|
configutil.validate_config(
|
||||||
|
"<test_everything_valid>",
|
||||||
|
cfg,
|
||||||
|
configutil.ValidConfiguration.nothing(),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_nothing_empty_valid(self):
|
||||||
|
"""
|
||||||
|
``validate_config`` returns ``None`` when the validator is
|
||||||
|
``ValidConfiguration.nothing()`` if the configuration is empty.
|
||||||
|
"""
|
||||||
|
cfg = ConfigParser()
|
||||||
|
self.assertIs(
|
||||||
|
configutil.validate_config(
|
||||||
|
"<test_everything_valid>",
|
||||||
|
cfg,
|
||||||
|
configutil.ValidConfiguration.nothing(),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
@ -115,10 +115,34 @@ class ValidConfiguration(object):
|
|||||||
an item name as bytes and returns True if that section, item pair is
|
an item name as bytes and returns True if that section, item pair is
|
||||||
valid, False otherwise.
|
valid, False otherwise.
|
||||||
"""
|
"""
|
||||||
_static_valid_sections = attr.ib()
|
_static_valid_sections = attr.ib(
|
||||||
|
validator=attr.validators.instance_of(dict)
|
||||||
|
)
|
||||||
_is_valid_section = attr.ib(default=lambda section_name: False)
|
_is_valid_section = attr.ib(default=lambda section_name: False)
|
||||||
_is_valid_item = attr.ib(default=lambda section_name, item_name: False)
|
_is_valid_item = attr.ib(default=lambda section_name, item_name: False)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def everything(cls):
|
||||||
|
"""
|
||||||
|
Create a validator which considers everything valid.
|
||||||
|
"""
|
||||||
|
return cls(
|
||||||
|
{},
|
||||||
|
lambda section_name: True,
|
||||||
|
lambda section_name, item_name: True,
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def nothing(cls):
|
||||||
|
"""
|
||||||
|
Create a validator which considers nothing valid.
|
||||||
|
"""
|
||||||
|
return cls(
|
||||||
|
{},
|
||||||
|
lambda section_name: False,
|
||||||
|
lambda section_name, item_name: False,
|
||||||
|
)
|
||||||
|
|
||||||
def is_valid_section(self, section_name):
|
def is_valid_section(self, section_name):
|
||||||
"""
|
"""
|
||||||
:return: True if the given section name is valid, False otherwise.
|
:return: True if the given section name is valid, False otherwise.
|
||||||
|
Loading…
Reference in New Issue
Block a user