diff options
-rw-r--r-- | ipalib/errors.py | 1 | ||||
-rw-r--r-- | ipalib/public.py | 16 | ||||
-rw-r--r-- | ipalib/tests/test_public.py | 57 |
3 files changed, 64 insertions, 10 deletions
diff --git a/ipalib/errors.py b/ipalib/errors.py index afc61dd8..a25df091 100644 --- a/ipalib/errors.py +++ b/ipalib/errors.py @@ -67,6 +67,7 @@ class RuleError(ValidationError): """ Raised when a required option was not provided. """ + # FIXME: `rule` should really be after `error` def __init__(self, name, value, rule, error): self.rule = rule ValidationError.__init__(self, name, value, error) diff --git a/ipalib/public.py b/ipalib/public.py index 4c2a8dd2..e0d9e6d2 100644 --- a/ipalib/public.py +++ b/ipalib/public.py @@ -88,6 +88,7 @@ class Option2(plugable.ReadOnly): def __init__(self, name, doc, type_, required=False, multivalue=False, default=None, default_from=None, normalize=None, rules=tuple() ): + self.name = name self.doc = doc self.type = type_ @@ -101,19 +102,16 @@ class Option2(plugable.ReadOnly): def validate_scalar(self, value): for rule in self.rules: - msg = rule(value) - if msg is not None: - raise errors.RuleError( - self.__class__.__name__, - value, - rule, - msg, - ) + error = rule(value) + if error is not None: + raise errors.RuleError(self.name, value, rule, error) def validate(self, value): if self.multivalue: if type(value) is not tuple: - value = (value,) + raise TypeError( + 'when multivalue, value must be tuple; got %r' % value + ) for v in value: self.validate_scalar(v) else: diff --git a/ipalib/tests/test_public.py b/ipalib/tests/test_public.py index 5b5d1d4b..ed4c75e5 100644 --- a/ipalib/tests/test_public.py +++ b/ipalib/tests/test_public.py @@ -128,7 +128,62 @@ class test_Option2(ClassChecker): assert read_only(o, 'default_from') is None assert read_only(o, 'rules') == (type_.validate,) - + def test_validate(self): + # Constructor arguments + name = 'sn' + doc = 'User last name' + type_ = ipa_types.Unicode() + def case_rule(value): + if not value.islower(): + return 'Must be lower case' + my_rules = (case_rule,) + + # Some test values: + okay = u'whatever' + fail_case = u'Whatever' + fail_type = 'whatever' + + # Test validate() and validate_scalar() when multivalue=False: + o = self.cls(name, doc, type_, rules=my_rules) + assert o.rules == (type_.validate, case_rule) + for m in [o.validate, o.validate_scalar]: + # Test a valid value: + m(okay) + # Check that RuleError is raised with wrong case: + e = raises(errors.RuleError, m, fail_case) + assert e.name is name + assert e.value is fail_case + assert e.error == 'Must be lower case' + # Test a RuleError is raise with wrong type: + e = raises(errors.RuleError, m, fail_type) + assert e.name is name + assert e.value is fail_type + assert e.error == 'Must be a string' + + # Test validate() when multivalue=True: + o = self.cls(name, doc, type_, multivalue=True, rules=my_rules) + def check_type_error(value): + e = raises(TypeError, o.validate, value) + assert str(e) == ( + 'when multivalue, value must be tuple; got %r' % value + ) + # Check a valid value: + check_type_error(okay) + o.validate((okay,)) + # Check that RuleError is raised with wrong case: + check_type_error(fail_case) + for value in [(okay, fail_case), (fail_case, okay)]: + e = raises(errors.RuleError, o.validate, value) + assert e.name is name + assert e.value is fail_case + assert e.error == 'Must be lower case' + # Test a RuleError is raise with wrong type: + check_type_error(fail_type) + for value in [(okay, fail_type), (fail_type, okay)]: + e = raises(errors.RuleError, o.validate, value) + assert e.name is name + assert e.value is fail_type + assert e.error == 'Must be a string' class test_Option(ClassChecker): |