summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipalib/errors.py1
-rw-r--r--ipalib/public.py16
-rw-r--r--ipalib/tests/test_public.py57
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):