summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test_ipalib/test_frontend.py519
-rw-r--r--tests/test_ipalib/test_ipa_types.py430
-rw-r--r--tests/test_ipalib/test_parameter.py531
-rw-r--r--tests/test_ipalib/test_parameters.py944
-rw-r--r--tests/util.py23
5 files changed, 1005 insertions, 1442 deletions
diff --git a/tests/test_ipalib/test_frontend.py b/tests/test_ipalib/test_frontend.py
index 94e586fe..071a70fd 100644
--- a/tests/test_ipalib/test_frontend.py
+++ b/tests/test_ipalib/test_frontend.py
@@ -23,7 +23,9 @@ Test the `ipalib.frontend` module.
from tests.util import raises, getitem, no_set, no_del, read_only
from tests.util import check_TypeError, ClassChecker, create_test_api
-from ipalib import frontend, backend, plugable, errors, ipa_types, config
+from tests.util import assert_equal
+from ipalib.constants import TYPE_ERROR
+from ipalib import frontend, backend, plugable, errors2, errors, parameters, config
def test_RULE_FLAG():
@@ -70,420 +72,6 @@ def test_is_rule():
assert not is_rule(call(None))
-class test_DefaultFrom(ClassChecker):
- """
- Test the `ipalib.frontend.DefaultFrom` class.
- """
- _cls = frontend.DefaultFrom
-
- def test_class(self):
- """
- Test the `ipalib.frontend.DefaultFrom` class.
- """
- assert self.cls.__bases__ == (plugable.ReadOnly,)
-
- def test_init(self):
- """
- Test the `ipalib.frontend.DefaultFrom.__init__` method.
- """
- def callback(*args):
- return args
- keys = ('givenname', 'sn')
- o = self.cls(callback, *keys)
- assert read_only(o, 'callback') is callback
- assert read_only(o, 'keys') == keys
- lam = lambda first, last: first[0] + last
- o = self.cls(lam)
- assert read_only(o, 'keys') == ('first', 'last')
-
- def test_call(self):
- """
- Test the `ipalib.frontend.DefaultFrom.__call__` method.
- """
- def callback(givenname, sn):
- return givenname[0] + sn[0]
- keys = ('givenname', 'sn')
- o = self.cls(callback, *keys)
- kw = dict(
- givenname='John',
- sn='Public',
- hello='world',
- )
- assert o(**kw) == 'JP'
- assert o() is None
- for key in ('givenname', 'sn'):
- kw_copy = dict(kw)
- del kw_copy[key]
- assert o(**kw_copy) is None
-
- # Test using implied keys:
- o = self.cls(lambda first, last: first[0] + last)
- assert o(first='john', last='doe') == 'jdoe'
- assert o(first='', last='doe') is None
- assert o(one='john', two='doe') is None
-
- # Test that co_varnames slice is used:
- def callback2(first, last):
- letter = first[0]
- return letter + last
- o = self.cls(callback2)
- assert o.keys == ('first', 'last')
- assert o(first='john', last='doe') == 'jdoe'
-
-
-def test_parse_param_spec():
- """
- Test the `ipalib.frontend.parse_param_spec` function.
- """
- f = frontend.parse_param_spec
-
- assert f('name') == ('name', dict(required=True, multivalue=False))
- assert f('name?') == ('name', dict(required=False, multivalue=False))
- assert f('name*') == ('name', dict(required=False, multivalue=True))
- assert f('name+') == ('name', dict(required=True, multivalue=True))
-
-
-class test_Param(ClassChecker):
- """
- Test the `ipalib.frontend.Param` class.
- """
- _cls = frontend.Param
-
- def test_class(self):
- """
- Test the `ipalib.frontend.Param` class.
- """
- assert self.cls.__bases__ == (plugable.ReadOnly,)
-
- def test_init(self):
- """
- Test the `ipalib.frontend.Param.__init__` method.
- """
- name = 'sn'
- o = self.cls(name)
- assert o.__islocked__() is True
-
- # Test default values
- assert read_only(o, 'name') is name
- assert read_only(o, 'cli_name') is name
- assert isinstance(read_only(o, 'type'), ipa_types.Unicode)
- assert read_only(o, 'doc') == ''
- assert read_only(o, 'required') is True
- assert read_only(o, 'multivalue') is False
- assert read_only(o, 'default') is None
- assert read_only(o, 'default_from') is None
- assert read_only(o, 'flags') == frozenset()
- assert read_only(o, 'rules') == tuple()
- assert len(read_only(o, 'all_rules')) == 1
- assert read_only(o, 'primary_key') is False
-
- # Test all kw args:
- t = ipa_types.Int()
- assert self.cls(name, cli_name='last').cli_name == 'last'
- assert self.cls(name, type=t).type is t
- assert self.cls(name, doc='the doc').doc == 'the doc'
- assert self.cls(name, required=False).required is False
- assert self.cls(name, multivalue=True).multivalue is True
- assert self.cls(name, default=u'Hello').default == u'Hello'
- df = frontend.DefaultFrom(lambda f, l: f + l,
- 'first', 'last',
- )
- lam = lambda first, last: first + last
- for cb in (df, lam):
- o = self.cls(name, default_from=cb)
- assert type(o.default_from) is frontend.DefaultFrom
- assert o.default_from.keys == ('first', 'last')
- assert o.default_from.callback('butt', 'erfly') == 'butterfly'
- assert self.cls(name, flags=('one', 'two', 'three')).flags == \
- frozenset(['one', 'two', 'three'])
- rules = (lambda whatever: 'Not okay!',)
- o = self.cls(name, rules=rules)
- assert o.rules is rules
- assert o.all_rules[1:] == rules
- assert self.cls(name, primary_key=True).primary_key is True
-
- # Test default type_:
- o = self.cls(name)
- assert isinstance(o.type, ipa_types.Unicode)
-
- # Test param spec parsing:
- o = self.cls('name?')
- assert o.name == 'name'
- assert o.required is False
- assert o.multivalue is False
-
- o = self.cls('name*')
- assert o.name == 'name'
- assert o.required is False
- assert o.multivalue is True
-
- o = self.cls('name+')
- assert o.name == 'name'
- assert o.required is True
- assert o.multivalue is True
-
- e = raises(TypeError, self.cls, name, whatever=True, another=False)
- assert str(e) == \
- 'Param.__init__() takes no such kwargs: another, whatever'
-
- def test_ispassword(self):
- """
- Test the `ipalib.frontend.Param.ispassword` method.
- """
- name = 'userpassword'
- okay = 'password'
- nope = ['', 'pass', 'word', 'passwd']
- for flag in nope:
- o = self.cls(name, flags=[flag])
- assert o.ispassword() is False
- o = self.cls(name, flags=[flag, okay])
- assert o.ispassword() is True
- assert self.cls(name).ispassword() is False
- assert self.cls(name, flags=[okay]).ispassword() is True
- assert self.cls(name, flags=[okay]+nope).ispassword() is True
-
- def test_clone(self):
- """
- Test the `ipalib.frontend.Param.__clone__` method.
- """
- def compare(o, kw):
- for (k, v) in kw.iteritems():
- assert getattr(o, k) == v, (k, v, getattr(o, k))
- default = dict(
- required=False,
- multivalue=False,
- default=None,
- default_from=None,
- rules=tuple(),
- )
- name = 'hair_color?'
- type_ = ipa_types.Int()
- o = self.cls(name, type=type_)
- compare(o, default)
-
- override = dict(multivalue=True, default=42)
- d = dict(default)
- d.update(override)
- clone = o.__clone__(**override)
- assert clone.name == 'hair_color'
- assert clone.type is o.type
- compare(clone, d)
-
- def test_convert(self):
- """
- Test the `ipalib.frontend.Param.convert` method.
- """
- name = 'some_number'
- type_ = ipa_types.Int()
- okay = (7, 7L, 7.0, ' 7 ')
- fail = ('7.0', '7L', 'whatever', object)
- none = (None, '', u'', tuple(), [])
-
- # Scenario 1: multivalue=False
- o = self.cls(name, type=type_)
- for n in none:
- assert o.convert(n) is None
- for value in okay:
- new = o.convert(value)
- assert new == 7
- assert type(new) is int
- for value in fail:
- e = raises(errors.ConversionError, o.convert, value)
- assert e.name is name
- assert e.value is value
- assert e.error is type_.conversion_error
- assert e.index is None
-
- # Scenario 2: multivalue=True
- o = self.cls(name, type=type_, multivalue=True)
- for n in none:
- assert o.convert(n) is None
- for value in okay:
- assert o.convert((value,)) == (7,)
- assert o.convert([value]) == (7,)
- assert o.convert(okay) == tuple(int(v) for v in okay)
- cnt = 5
- for value in fail:
- for i in xrange(cnt):
- others = list(7 for x in xrange(cnt))
- others[i] = value
- for v in [tuple(others), list(others)]:
- e = raises(errors.ConversionError, o.convert, v)
- assert e.name is name
- assert e.value is value
- assert e.error is type_.conversion_error
- assert e.index == i
-
- def test_normalize(self):
- """
- Test the `ipalib.frontend.Param.normalize` method.
- """
- name = 'sn'
- callback = lambda value: value.lower()
- values = (None, u'Hello', (u'Hello',), 'hello', ['hello'])
- none = (None, '', u'', tuple(), [])
-
- # Scenario 1: multivalue=False, normalize=None
- o = self.cls(name)
- for v in values:
- # When normalize=None, value is returned, no type checking:
- assert o.normalize(v) is v
-
- # Scenario 2: multivalue=False, normalize=callback
- o = self.cls(name, normalize=callback)
- for v in (u'Hello', u'hello', 'Hello'): # Okay
- assert o.normalize(v) == 'hello'
- for v in [None, 42, (u'Hello',)]: # Not basestring
- assert o.normalize(v) is v
- for n in none:
- assert o.normalize(n) is None
-
- # Scenario 3: multivalue=True, normalize=None
- o = self.cls(name, multivalue=True)
- for v in values:
- # When normalize=None, value is returned, no type checking:
- assert o.normalize(v) is v
-
- # Scenario 4: multivalue=True, normalize=callback
- o = self.cls(name, multivalue=True, normalize=callback)
- assert o.normalize([]) is None
- assert o.normalize(tuple()) is None
- for value in [(u'Hello',), (u'hello',), 'Hello', ['Hello']]: # Okay
- assert o.normalize(value) == (u'hello',)
- fail = 42 # Not basestring
- for v in [[fail], (u'hello', fail)]: # Non basestring member
- assert o.normalize(v) == tuple(v)
- for n in none:
- assert o.normalize(n) is None
-
- def test_validate(self):
- """
- Test the `ipalib.frontend.Param.validate` method.
- """
- name = 'sn'
- type_ = ipa_types.Unicode()
- def case_rule(value):
- if not value.islower():
- return 'Must be lower case'
- my_rules = (case_rule,)
- okay = u'whatever'
- fail_case = u'Whatever'
- fail_type = 'whatever'
-
- # Scenario 1: multivalue=False
- o = self.cls(name, type=type_, rules=my_rules)
- assert o.rules == my_rules
- assert o.all_rules == (type_.validate, case_rule)
- o.validate(okay)
- e = raises(errors.RuleError, o.validate, fail_case)
- assert e.name is name
- assert e.value is fail_case
- assert e.error == 'Must be lower case'
- assert e.rule is case_rule
- assert e.index is None
- check_TypeError(fail_type, unicode, 'value', o.validate, fail_type)
-
- ## Scenario 2: multivalue=True
- o = self.cls(name, type=type_, multivalue=True, rules=my_rules)
- o.validate((okay,))
- cnt = 5
- for i in xrange(cnt):
- others = list(okay for x in xrange(cnt))
- others[i] = fail_case
- value = tuple(others)
- 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'
- assert e.rule is case_rule
- assert e.index == i
- for not_tuple in (okay, [okay]):
- check_TypeError(not_tuple, tuple, 'value', o.validate, not_tuple)
- for has_str in [(fail_type,), (okay, fail_type)]:
- check_TypeError(fail_type, unicode, 'value', o.validate, has_str)
-
- def test_get_default(self):
- """
- Test the `ipalib.frontend.Param.get_default` method.
- """
- name = 'greeting'
- default = u'Hello, world!'
- default_from = frontend.DefaultFrom(
- lambda first, last: u'Hello, %s %s!' % (first, last),
- 'first', 'last'
- )
-
- # Scenario 1: multivalue=False
- o = self.cls(name,
- default=default,
- default_from=default_from,
- )
- assert o.default is default
- assert o.default_from is default_from
- assert o.get_default() == default
- assert o.get_default(first='John', last='Doe') == 'Hello, John Doe!'
-
- # Scenario 2: multivalue=True
- default = (default,)
- o = self.cls(name,
- default=default,
- default_from=default_from,
- multivalue=True,
- )
- assert o.default is default
- assert o.default_from is default_from
- assert o.get_default() == default
- assert o.get_default(first='John', last='Doe') == ('Hello, John Doe!',)
-
- def test_get_value(self):
- """
- Test the `ipalib.frontend.Param.get_values` method.
- """
- name = 'status'
- values = (u'Active', u'Inactive')
- o = self.cls(name, type=ipa_types.Unicode())
- assert o.get_values() == tuple()
- o = self.cls(name, type=ipa_types.Enum(*values))
- assert o.get_values() == values
-
- def test_repr(self):
- """
- Test the `ipalib.frontend.Param.__repr__` method.
- """
- for name in ['name', 'name?', 'name*', 'name+']:
- o = self.cls(name)
- assert repr(o) == 'Param(%r)' % name
- o = self.cls('name', required=False)
- assert repr(o) == "Param('name', required=False)"
- o = self.cls('name', multivalue=True)
- assert repr(o) == "Param('name', multivalue=True)"
-
-
-def test_create_param():
- """
- Test the `ipalib.frontend.create_param` function.
- """
- f = frontend.create_param
- for name in ['arg', 'arg?', 'arg*', 'arg+']:
- o = f(name)
- assert type(o) is frontend.Param
- assert type(o.type) is ipa_types.Unicode
- assert o.name == 'arg'
- assert f(o) is o
- o = f('arg')
- assert o.required is True
- assert o.multivalue is False
- o = f('arg?')
- assert o.required is False
- assert o.multivalue is False
- o = f('arg*')
- assert o.required is False
- assert o.multivalue is True
- o = f('arg+')
- assert o.required is True
- assert o.multivalue is True
-
-
class test_Command(ClassChecker):
"""
Test the `ipalib.frontend.Command` class.
@@ -499,28 +87,25 @@ class test_Command(ClassChecker):
def __init__(self, name):
self.name = name
- def __call__(self, value):
+ def __call__(self, _, value):
if value != self.name:
- return 'must equal %s' % self.name
+ return _('must equal %r') % self.name
- default_from = frontend.DefaultFrom(
+ default_from = parameters.DefaultFrom(
lambda arg: arg,
'default_from'
)
- normalize = lambda value: value.lower()
+ normalizer = lambda value: value.lower()
class example(self.cls):
takes_options = (
- frontend.Param('option0',
- normalize=normalize,
+ parameters.Str('option0', Rule('option0'),
+ normalizer=normalizer,
default_from=default_from,
- rules=(Rule('option0'),)
),
- frontend.Param('option1',
- normalize=normalize,
+ parameters.Str('option1', Rule('option1'),
+ normalizer=normalizer,
default_from=default_from,
- rules=(Rule('option1'),),
- required=True,
),
)
return example
@@ -577,8 +162,8 @@ class test_Command(ClassChecker):
assert type(ns) is plugable.NameSpace
assert len(ns) == len(args)
assert list(ns) == ['destination', 'source']
- assert type(ns.destination) is frontend.Param
- assert type(ns.source) is frontend.Param
+ assert type(ns.destination) is parameters.Str
+ assert type(ns.source) is parameters.Str
assert ns.destination.required is True
assert ns.destination.multivalue is False
assert ns.source.required is False
@@ -586,8 +171,8 @@ class test_Command(ClassChecker):
# Test TypeError:
e = raises(TypeError, self.get_instance, args=(u'whatever',))
- assert str(e) == \
- 'create_param() takes %r or %r; got %r' % (str, frontend.Param, u'whatever')
+ assert str(e) == TYPE_ERROR % (
+ 'spec', (str, parameters.Param), u'whatever', unicode)
# Test ValueError, required after optional:
e = raises(ValueError, self.get_instance, args=('arg1?', 'arg2'))
@@ -627,8 +212,8 @@ class test_Command(ClassChecker):
assert type(ns) is plugable.NameSpace
assert len(ns) == len(options)
assert list(ns) == ['target', 'files']
- assert type(ns.target) is frontend.Param
- assert type(ns.files) is frontend.Param
+ assert type(ns.target) is parameters.Str
+ assert type(ns.files) is parameters.Str
assert ns.target.required is True
assert ns.target.multivalue is False
assert ns.files.required is False
@@ -640,17 +225,13 @@ class test_Command(ClassChecker):
"""
assert 'convert' in self.cls.__public__ # Public
kw = dict(
- option0='option0',
- option1='option1',
+ option0=u'1.5',
+ option1=u'7',
)
- expected = dict(kw)
- expected.update(dict(option0=u'option0', option1=u'option1'))
o = self.subcls()
o.finalize()
for (key, value) in o.convert(**kw).iteritems():
- v = expected[key]
- assert value == v
- assert type(value) is type(v)
+ assert_equal(unicode(kw[key]), value)
def test_normalize(self):
"""
@@ -671,22 +252,7 @@ class test_Command(ClassChecker):
Test the `ipalib.frontend.Command.get_default` method.
"""
assert 'get_default' in self.cls.__public__ # Public
- no_fill = dict(
- option0='value0',
- option1='value1',
- whatever='hello world',
- )
- fill = dict(
- default_from='the default',
- )
- default = dict(
- option0='the default',
- option1='the default',
- )
- sub = self.subcls()
- sub.finalize()
- assert sub.get_default(**no_fill) == {}
- assert sub.get_default(**fill) == default
+ # FIXME: Add an updated unit tests for get_default()
def test_validate(self):
"""
@@ -697,7 +263,7 @@ class test_Command(ClassChecker):
sub = self.subcls()
sub.finalize()
- # Check with valid args
+ # Check with valid values
okay = dict(
option0=u'option0',
option1=u'option1',
@@ -705,13 +271,13 @@ class test_Command(ClassChecker):
)
sub.validate(**okay)
- # Check with an invalid arg
+ # Check with an invalid value
fail = dict(okay)
fail['option0'] = u'whatever'
- e = raises(errors.RuleError, sub.validate, **fail)
- assert e.name == 'option0'
- assert e.value == u'whatever'
- assert e.error == 'must equal option0'
+ e = raises(errors2.ValidationError, sub.validate, **fail)
+ assert_equal(e.name, 'option0')
+ assert_equal(e.value, u'whatever')
+ assert_equal(e.error, u"must equal 'option0'")
assert e.rule.__class__.__name__ == 'Rule'
assert e.index is None
@@ -845,9 +411,9 @@ class test_LocalOrRemote(ClassChecker):
api.finalize()
cmd = api.Command.example
assert cmd() == ('execute', (None,), dict(server=False))
- assert cmd('var') == ('execute', (u'var',), dict(server=False))
+ assert cmd(u'var') == ('execute', (u'var',), dict(server=False))
assert cmd(server=True) == ('forward', (None,), dict(server=True))
- assert cmd('var', server=True) == \
+ assert cmd(u'var', server=True) == \
('forward', (u'var',), dict(server=True))
# Test when in_server=True (should always call execute):
@@ -856,9 +422,9 @@ class test_LocalOrRemote(ClassChecker):
api.finalize()
cmd = api.Command.example
assert cmd() == ('execute', (None,), dict(server=False))
- assert cmd('var') == ('execute', (u'var',), dict(server=False))
+ assert cmd(u'var') == ('execute', (u'var',), dict(server=False))
assert cmd(server=True) == ('execute', (None,), dict(server=True))
- assert cmd('var', server=True) == \
+ assert cmd(u'var', server=True) == \
('execute', (u'var',), dict(server=True))
@@ -974,7 +540,7 @@ class test_Object(ClassChecker):
assert len(ns) == 2, repr(ns)
assert list(ns) == ['banana', 'apple']
for p in ns():
- assert type(p) is frontend.Param
+ assert type(p) is parameters.Str
assert p.required is True
assert p.multivalue is False
@@ -1001,15 +567,13 @@ class test_Object(ClassChecker):
takes_params = (
'one',
'two',
- frontend.Param('three',
- primary_key=True,
- ),
+ parameters.Str('three', primary_key=True),
'four',
)
o = example2()
o.set_api(api)
pk = o.primary_key
- assert isinstance(pk, frontend.Param)
+ assert type(pk) is parameters.Str
assert pk.name == 'three'
assert pk.primary_key is True
assert o.params[2] is o.primary_key
@@ -1019,10 +583,10 @@ class test_Object(ClassChecker):
# Test with multiple primary_key:
class example3(self.cls):
takes_params = (
- frontend.Param('one', primary_key=True),
- frontend.Param('two', primary_key=True),
+ parameters.Str('one', primary_key=True),
+ parameters.Str('two', primary_key=True),
'three',
- frontend.Param('four', primary_key=True),
+ parameters.Str('four', primary_key=True),
)
o = example3()
e = raises(ValueError, o.set_api, api)
@@ -1155,12 +719,7 @@ class test_Property(ClassChecker):
Test the `ipalib.frontend.Property` class.
"""
assert self.cls.__bases__ == (frontend.Attribute,)
- assert isinstance(self.cls.type, ipa_types.Unicode)
- assert self.cls.required is False
- assert self.cls.multivalue is False
- assert self.cls.default is None
- assert self.cls.default_from is None
- assert self.cls.normalize is None
+ assert self.cls.klass is parameters.Str
def test_init(self):
"""
@@ -1170,7 +729,7 @@ class test_Property(ClassChecker):
assert len(o.rules) == 1
assert o.rules[0].__name__ == 'rule0_lowercase'
param = o.param
- assert isinstance(param, frontend.Param)
+ assert isinstance(param, parameters.Str)
assert param.name == 'givenname'
assert param.doc == 'User first name'
diff --git a/tests/test_ipalib/test_ipa_types.py b/tests/test_ipalib/test_ipa_types.py
deleted file mode 100644
index eb166069..00000000
--- a/tests/test_ipalib/test_ipa_types.py
+++ /dev/null
@@ -1,430 +0,0 @@
-# Authors:
-# Jason Gerard DeRose <jderose@redhat.com>
-#
-# Copyright (C) 2008 Red Hat
-# see file 'COPYING' for use and warranty information
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; version 2 only
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-Test the `ipalib.ipa_types` module.
-"""
-
-from tests.util import raises, getitem, no_set, no_del, read_only, ClassChecker
-from ipalib import ipa_types, errors, plugable
-
-
-def test_check_min_max():
- """
- Test the `ipalib.ipa_types.check_min_max` function.
- """
- f = ipa_types.check_min_max
- okay = [
- (None, -5),
- (-20, None),
- (-20, -5),
- ]
- for (l, h) in okay:
- assert f(l, h, 'low', 'high') is None
- fail_type = [
- '10',
- 10.0,
- 10L,
- True,
- False,
- object,
- ]
- for value in fail_type:
- e = raises(TypeError, f, value, None, 'low', 'high')
- assert str(e) == 'low must be an int or None, got: %r' % value
- e = raises(TypeError, f, None, value, 'low', 'high')
- assert str(e) == 'high must be an int or None, got: %r' % value
- fail_value = [
- (10, 5),
- (-5, -10),
- (5, -10),
- ]
- for (l, h) in fail_value:
- e = raises(ValueError, f, l, h, 'low', 'high')
- assert str(e) == 'low > high: low=%r, high=%r' % (l, h)
-
-
-class test_Type(ClassChecker):
- """
- Test the `ipalib.ipa_types.Type` class.
- """
- _cls = ipa_types.Type
-
- def test_class(self):
- """
- Test the `ipalib.ipa_types.Type` class.
- """
- assert self.cls.__bases__ == (plugable.ReadOnly,)
-
- def test_init(self):
- """
- Test the `ipalib.ipa_types.Type.__init__` method.
- """
- okay = (bool, int, float, unicode)
- for t in okay:
- o = self.cls(t)
- assert o.__islocked__() is True
- assert read_only(o, 'type') is t
- assert read_only(o, 'name') is 'Type'
-
- type_errors = (None, True, 8, 8.0, u'hello')
- for t in type_errors:
- e = raises(TypeError, self.cls, t)
- assert str(e) == '%r is not %r' % (type(t), type)
-
- value_errors = (long, complex, str, tuple, list, dict, set, frozenset)
- for t in value_errors:
- e = raises(ValueError, self.cls, t)
- assert str(e) == 'not an allowed type: %r' % t
-
- def test_validate(self):
- """
- Test the `ipalib.ipa_types.Type.validate` method.
- """
- o = self.cls(unicode)
- for value in (None, u'Hello', 'Hello', 42, False):
- assert o.validate(value) is None
-
-
-class test_Bool(ClassChecker):
- """
- Test the `ipalib.ipa_types.Bool` class.
- """
- _cls = ipa_types.Bool
-
- def test_class(self):
- """
- Test the `ipalib.ipa_types.Bool` class.
- """
- assert self.cls.__bases__ == (ipa_types.Type,)
-
- def test_init(self):
- """
- Test the `ipalib.ipa_types.Bool.__init__` method.
- """
- o = self.cls()
- assert o.__islocked__() is True
- assert read_only(o, 'type') is bool
- assert read_only(o, 'name') == 'Bool'
- assert read_only(o, 'true') == 'Yes'
- assert read_only(o, 'false') == 'No'
-
- keys = ('true', 'false')
- val = 'some value'
- for key in keys:
- # Check that kwarg sets appropriate attribute:
- o = self.cls(**{key: val})
- assert read_only(o, key) is val
- # Check that None raises TypeError:
- e = raises(TypeError, self.cls, **{key: None})
- assert str(e) == '`%s` cannot be None' % key
-
- # Check that ValueError is raise if true == false:
- e = raises(ValueError, self.cls, true=1L, false=1.0)
- assert str(e) == 'cannot be equal: true=1L, false=1.0'
-
- def test_call(self):
- """
- Test the `ipalib.ipa_types.Bool.__call__` method.
- """
- o = self.cls()
- assert o(True) is True
- assert o('Yes') is True
- assert o(False) is False
- assert o('No') is False
- for value in (0, 1, 'True', 'False', 'yes', 'no'):
- # value is not be converted, so None is returned
- assert o(value) is None
-
-
-class test_Int(ClassChecker):
- """
- Test the `ipalib.ipa_types.Int` class.
- """
- _cls = ipa_types.Int
-
- def test_class(self):
- """
- Test the `ipalib.ipa_types.Int` class.
- """
- assert self.cls.__bases__ == (ipa_types.Type,)
-
- def test_init(self):
- """
- Test the `ipalib.ipa_types.Int.__init__` method.
- """
- o = self.cls()
- assert o.__islocked__() is True
- assert read_only(o, 'type') is int
- assert read_only(o, 'name') == 'Int'
- assert read_only(o, 'min_value') is None
- assert read_only(o, 'max_value') is None
-
- okay = [
- (None, -5),
- (-20, None),
- (-20, -5),
- ]
- for (l, h) in okay:
- o = self.cls(min_value=l, max_value=h)
- assert o.min_value is l
- assert o.max_value is h
-
- fail_type = [
- '10',
- 10.0,
- 10L,
- True,
- False,
- object,
- ]
- for value in fail_type:
- e = raises(TypeError, self.cls, min_value=value)
- assert str(e) == (
- 'min_value must be an int or None, got: %r' % value
- )
- e = raises(TypeError, self.cls, max_value=value)
- assert str(e) == (
- 'max_value must be an int or None, got: %r' % value
- )
-
- fail_value = [
- (10, 5),
- (5, -5),
- (-5, -10),
- ]
- for (l, h) in fail_value:
- e = raises(ValueError, self.cls, min_value=l, max_value=h)
- assert str(e) == (
- 'min_value > max_value: min_value=%d, max_value=%d' % (l, h)
- )
-
- def test_call(self):
- """
- Test the `ipalib.ipa_types.Int.__call__` method.
- """
- o = self.cls()
-
- # Test calling with None
- e = raises(TypeError, o, None)
- assert str(e) == 'value cannot be None'
-
- # Test with values that can be converted:
- okay = [
- 3,
- '3',
- ' 3 ',
- 3L,
- 3.0,
- ]
- for value in okay:
- assert o(value) == 3
-
- # Test with values that cannot be converted:
- fail = [
- object,
- '3.0',
- '3L',
- 'whatever',
- ]
- for value in fail:
- assert o(value) is None
-
- def test_validate(self):
- """
- Test the `ipalib.ipa_types.Int.validate` method.
- """
- o = self.cls(min_value=2, max_value=7)
- assert o.validate(2) is None
- assert o.validate(5) is None
- assert o.validate(7) is None
- assert o.validate(1) == 'Cannot be smaller than 2'
- assert o.validate(8) == 'Cannot be larger than 7'
- for val in ['5', 5.0, 5L, None, True, False, object]:
- assert o.validate(val) == 'Must be an integer'
-
-
-class test_Unicode(ClassChecker):
- """
- Test the `ipalib.ipa_types.Unicode` class.
- """
- _cls = ipa_types.Unicode
-
- def test_class(self):
- """
- Test the `ipalib.ipa_types.Unicode` class.
- """
- assert self.cls.__bases__ == (ipa_types.Type,)
-
- def test_init(self):
- """
- Test the `ipalib.ipa_types.Unicode.__init__` method.
- """
- o = self.cls()
- assert o.__islocked__() is True
- assert read_only(o, 'type') is unicode
- assert read_only(o, 'name') == 'Unicode'
- assert read_only(o, 'min_length') is None
- assert read_only(o, 'max_length') is None
- assert read_only(o, 'pattern') is None
- assert read_only(o, 'regex') is None
-
- # Test min_length, max_length:
- okay = (
- (0, 1),
- (8, 8),
- )
- for (l, h) in okay:
- o = self.cls(min_length=l, max_length=h)
- assert o.min_length == l
- assert o.max_length == h
-
- fail_type = [
- '10',
- 10.0,
- 10L,
- True,
- False,
- object,
- ]
- for value in fail_type:
- e = raises(TypeError, self.cls, min_length=value)
- assert str(e) == (
- 'min_length must be an int or None, got: %r' % value
- )
- e = raises(TypeError, self.cls, max_length=value)
- assert str(e) == (
- 'max_length must be an int or None, got: %r' % value
- )
-
- fail_value = [
- (10, 5),
- (5, -5),
- (0, -10),
- ]
- for (l, h) in fail_value:
- e = raises(ValueError, self.cls, min_length=l, max_length=h)
- assert str(e) == (
- 'min_length > max_length: min_length=%d, max_length=%d' % (l, h)
- )
-
- for (key, lower) in [('min_length', 0), ('max_length', 1)]:
- value = lower - 1
- kw = {key: value}
- e = raises(ValueError, self.cls, **kw)
- assert str(e) == '%s must be >= %d, got: %d' % (key, lower, value)
-
- # Test pattern:
- okay = [
- '(hello|world)',
- u'(take the blue pill|take the red pill)',
- ]
- for value in okay:
- o = self.cls(pattern=value)
- assert o.pattern is value
- assert o.regex is not None
-
- fail = [
- 42,
- True,
- False,
- object,
- ]
- for value in fail:
- e = raises(TypeError, self.cls, pattern=value)
- assert str(e) == (
- 'pattern must be a basestring or None, got: %r' % value
- )
-
- # Test regex:
- pat = '^(hello|world)$'
- o = self.cls(pattern=pat)
- for value in ('hello', 'world'):
- m = o.regex.match(value)
- assert m.group(1) == value
- for value in ('hello beautiful', 'world!'):
- assert o.regex.match(value) is None
-
- def test_validate(self):
- """
- Test the `ipalib.ipa_types.Unicode.validate` method.
- """
- pat = '^a_*b$'
- o = self.cls(min_length=3, max_length=4, pattern=pat)
- assert o.validate(u'a_b') is None
- assert o.validate(u'a__b') is None
- assert o.validate('a_b') == 'Must be a string'
- assert o.validate(u'ab') == 'Must be at least 3 characters long'
- assert o.validate(u'a___b') == 'Can be at most 4 characters long'
- assert o.validate(u'a-b') == 'Must match %r' % pat
- assert o.validate(u'a--b') == 'Must match %r' % pat
-
-
-class test_Enum(ClassChecker):
- """
- Test the `ipalib.ipa_types.Enum` class.
- """
- _cls = ipa_types.Enum
-
- def test_class(self):
- """
- Test the `ipalib.ipa_types.Enum` class.
- """
- assert self.cls.__bases__ == (ipa_types.Type,)
-
- def test_init(self):
- """
- Test the `ipalib.ipa_types.Enum.__init__` method.
- """
- for t in (unicode, int, float):
- values = (t(1), t(2), t(3))
- o = self.cls(*values)
- assert o.__islocked__() is True
- assert read_only(o, 'type') is t
- assert read_only(o, 'name') is 'Enum'
- assert read_only(o, 'values') == values
- assert read_only(o, 'frozenset') == frozenset(values)
-
- # Check that ValueError is raised when no values are given:
- e = raises(ValueError, self.cls)
- assert str(e) == 'Enum requires at least one value'
-
- # Check that TypeError is raised when type of first value is not
- # allowed:
- e = raises(TypeError, self.cls, 'hello')
- assert str(e) == '%r: %r not unicode, int, nor float' % ('hello', str)
- #self.cls('hello')
-
- # Check that TypeError is raised when subsequent values aren't same
- # type as first:
- e = raises(TypeError, self.cls, u'hello', 'world')
- assert str(e) == '%r: %r is not %r' % ('world', str, unicode)
-
- def test_validate(self):
- """
- Test the `ipalib.ipa_types.Enum.validate` method.
- """
- values = (u'hello', u'naughty', u'nurse')
- o = self.cls(*values)
- for value in values:
- assert o.validate(value) is None
- assert o.validate(str(value)) == 'Incorrect type'
- for value in (u'one fish', u'two fish'):
- assert o.validate(value) == 'Invalid value'
- assert o.validate(str(value)) == 'Incorrect type'
diff --git a/tests/test_ipalib/test_parameter.py b/tests/test_ipalib/test_parameter.py
deleted file mode 100644
index e2016f06..00000000
--- a/tests/test_ipalib/test_parameter.py
+++ /dev/null
@@ -1,531 +0,0 @@
-# Authors:
-# Jason Gerard DeRose <jderose@redhat.com>
-#
-# Copyright (C) 2008 Red Hat
-# see file 'COPYING' for use and warranty information
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation; version 2 only
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-"""
-Test the `ipalib.parameter` module.
-"""
-
-from tests.util import raises, ClassChecker, read_only
-from tests.util import dummy_ugettext, assert_equal
-from tests.data import binary_bytes, utf8_bytes, unicode_str
-from ipalib import parameter, request
-from ipalib.constants import TYPE_ERROR, CALLABLE_ERROR, NULLS
-
-
-class test_DefaultFrom(ClassChecker):
- """
- Test the `ipalib.parameter.DefaultFrom` class.
- """
- _cls = parameter.DefaultFrom
-
- def test_init(self):
- """
- Test the `ipalib.parameter.DefaultFrom.__init__` method.
- """
- def callback(*args):
- return args
- keys = ('givenname', 'sn')
- o = self.cls(callback, *keys)
- assert read_only(o, 'callback') is callback
- assert read_only(o, 'keys') == keys
- lam = lambda first, last: first[0] + last
- o = self.cls(lam)
- assert read_only(o, 'keys') == ('first', 'last')
-
- # Test that TypeError is raised when callback isn't callable:
- e = raises(TypeError, self.cls, 'whatever')
- assert str(e) == CALLABLE_ERROR % ('callback', 'whatever', str)
-
- # Test that TypeError is raised when a key isn't an str:
- e = raises(TypeError, self.cls, callback, 'givenname', 17)
- assert str(e) == TYPE_ERROR % ('keys', str, 17, int)
-
- def test_call(self):
- """
- Test the `ipalib.parameter.DefaultFrom.__call__` method.
- """
- def callback(givenname, sn):
- return givenname[0] + sn[0]
- keys = ('givenname', 'sn')
- o = self.cls(callback, *keys)
- kw = dict(
- givenname='John',
- sn='Public',
- hello='world',
- )
- assert o(**kw) == 'JP'
- assert o() is None
- for key in ('givenname', 'sn'):
- kw_copy = dict(kw)
- del kw_copy[key]
- assert o(**kw_copy) is None
-
- # Test using implied keys:
- o = self.cls(lambda first, last: first[0] + last)
- assert o(first='john', last='doe') == 'jdoe'
- assert o(first='', last='doe') is None
- assert o(one='john', two='doe') is None
-
- # Test that co_varnames slice is used:
- def callback2(first, last):
- letter = first[0]
- return letter + last
- o = self.cls(callback2)
- assert o.keys == ('first', 'last')
- assert o(first='john', last='doe') == 'jdoe'
-
-
-def test_parse_param_spec():
- """
- Test the `ipalib.parameter.parse_param_spec` function.
- """
- f = parameter.parse_param_spec
- assert f('name') == ('name', dict(required=True, multivalue=False))
- assert f('name?') == ('name', dict(required=False, multivalue=False))
- assert f('name*') == ('name', dict(required=False, multivalue=True))
- assert f('name+') == ('name', dict(required=True, multivalue=True))
-
- # Make sure other "funny" endings are *not* treated special:
- assert f('name^') == ('name^', dict(required=True, multivalue=False))
-
- # Test that TypeError is raised if spec isn't an str:
- e = raises(TypeError, f, u'name?')
- assert str(e) == TYPE_ERROR % ('spec', str, u'name?', unicode)
-
- # Test that ValueError is raised if len(spec) < 2:
- e = raises(ValueError, f, 'n')
- assert str(e) == "spec must be at least 2 characters; got 'n'"
-
-
-class test_Param(ClassChecker):
- """
- Test the `ipalib.parameter.Param` class.
- """
- _cls = parameter.Param
-
- def test_init(self):
- """
- Test the `ipalib.parameter.Param.__init__` method.
- """
- name = 'my_param'
- o = self.cls(name)
- assert o.param_spec is name
- assert o.name is name
- assert o.nice == "Param('my_param')"
- assert o.__islocked__() is True
-
- # Test default rules:
- assert o.rules == tuple()
- assert o.class_rules == tuple()
- assert o.all_rules == tuple()
-
- # Test default kwarg values:
- assert o.cli_name is name
- assert o.label is None
- assert o.doc == ''
- assert o.required is True
- assert o.multivalue is False
- assert o.primary_key is False
- assert o.normalizer is None
- assert o.default is None
- assert o.default_from is None
- assert o.flags == frozenset()
-
- # Test that ValueError is raised when a kwarg from a subclass
- # conflicts with an attribute:
- class Subclass(self.cls):
- kwargs = self.cls.kwargs + (
- ('convert', callable, None),
- )
- e = raises(ValueError, Subclass, name)
- assert str(e) == "kwarg 'convert' conflicts with attribute on Subclass"
-
- # Test type validation of keyword arguments:
- class Subclass(self.cls):
- kwargs = self.cls.kwargs + (
- ('extra1', bool, True),
- ('extra2', str, 'Hello'),
- ('extra3', (int, float), 42),
- ('extra4', callable, lambda whatever: whatever + 7),
- )
- o = Subclass('my_param') # Test with no **kw:
- for (key, kind, default) in o.kwargs:
- # Test with a type invalid for all:
- value = object()
- kw = {key: value}
- e = raises(TypeError, Subclass, 'my_param', **kw)
- if kind is callable:
- assert str(e) == CALLABLE_ERROR % (key, value, type(value))
- else:
- assert str(e) == TYPE_ERROR % (key, kind, value, type(value))
- # Test with None:
- kw = {key: None}
- Subclass('my_param', **kw)
-
- # Test when using unknown kwargs:
- e = raises(TypeError, self.cls, 'my_param',
- flags=['hello', 'world'],
- whatever=u'Hooray!',
- )
- assert str(e) == \
- "Param('my_param'): takes no such kwargs: 'whatever'"
- e = raises(TypeError, self.cls, 'my_param', great='Yes', ape='he is!')
- assert str(e) == \
- "Param('my_param'): takes no such kwargs: 'ape', 'great'"
-
- def test_repr(self):
- """
- Test the `ipalib.parameter.Param.__repr__` method.
- """
- for name in ['name', 'name?', 'name*', 'name+']:
- o = self.cls(name)
- assert repr(o) == 'Param(%r)' % name
- o = self.cls('name', required=False)
- assert repr(o) == "Param('name', required=False)"
- o = self.cls('name', multivalue=True)
- assert repr(o) == "Param('name', multivalue=True)"
-
- def test_get_label(self):
- """
- Test the `ipalib.parameter.get_label` method.
- """
- context = request.context
- cli_name = 'the_cli_name'
- message = 'The Label'
- label = lambda _: _(message)
- o = self.cls('name', cli_name=cli_name, label=label)
- assert o.label is label
-
- ## Scenario 1: label=callable (a lambda form)
-
- # Test with no context.ugettext:
- assert not hasattr(context, 'ugettext')
- assert_equal(o.get_label(), u'The Label')
-
- # Test with dummy context.ugettext:
- assert not hasattr(context, 'ugettext')
- dummy = dummy_ugettext()
- context.ugettext = dummy
- assert o.get_label() is dummy.translation
- assert dummy.message is message
- del context.ugettext
-
- ## Scenario 2: label=None
- o = self.cls('name', cli_name=cli_name)
- assert o.label is None
-
- # Test with no context.ugettext:
- assert not hasattr(context, 'ugettext')
- assert_equal(o.get_label(), u'the_cli_name')
-
- # Test with dummy context.ugettext:
- assert not hasattr(context, 'ugettext')
- dummy = dummy_ugettext()
- context.ugettext = dummy
- assert_equal(o.get_label(), u'the_cli_name')
- assert not hasattr(dummy, 'message')
-
- # Cleanup
- del context.ugettext
- assert not hasattr(context, 'ugettext')
-
- def test_convert(self):
- """
- Test the `ipalib.parameter.Param.convert` method.
- """
- okay = ('Hello', u'Hello', 0, 4.2, True, False)
- class Subclass(self.cls):
- def _convert_scalar(self, value, index=None):
- return value
-
- # Test when multivalue=False:
- o = Subclass('my_param')
- for value in NULLS:
- assert o.convert(value) is None
- for value in okay:
- assert o.convert(value) is value
-
- # Test when multivalue=True:
- o = Subclass('my_param', multivalue=True)
- for value in NULLS:
- assert o.convert(value) is None
- assert o.convert(okay) == okay
- assert o.convert(NULLS) is None
- assert o.convert(okay + NULLS) == okay
- assert o.convert(NULLS + okay) == okay
- for value in okay:
- assert o.convert(value) == (value,)
- assert o.convert([None, value]) == (value,)
- assert o.convert([value, None]) == (value,)
-
- def test_convert_scalar(self):
- """
- Test the `ipalib.parameter.Param._convert_scalar` method.
- """
- o = self.cls('my_param')
- e = raises(NotImplementedError, o._convert_scalar, 'some value')
- assert str(e) == 'Param._convert_scalar()'
- class Subclass(self.cls):
- pass
- o = Subclass('my_param')
- e = raises(NotImplementedError, o._convert_scalar, 'some value')
- assert str(e) == 'Subclass._convert_scalar()'
-
-
-class test_Bytes(ClassChecker):
- """
- Test the `ipalib.parameter.Bytes` class.
- """
- _cls = parameter.Bytes
-
- def test_init(self):
- """
- Test the `ipalib.parameter.Bytes.__init__` method.
- """
- o = self.cls('my_bytes')
- assert o.type is str
- assert o.rules == tuple()
- assert o.class_rules == tuple()
- assert o.all_rules == tuple()
- assert o.minlength is None
- assert o.maxlength is None
- assert o.length is None
- assert o.pattern is None
-
- # Test mixing length with minlength or maxlength:
- o = self.cls('my_bytes', length=5)
- assert o.length == 5
- assert len(o.class_rules) == 1
- assert len(o.rules) == 0
- assert len(o.all_rules) == 1
- permutations = [
- dict(minlength=3),
- dict(maxlength=7),
- dict(minlength=3, maxlength=7),
- ]
- for kw in permutations:
- o = self.cls('my_bytes', **kw)
- assert len(o.class_rules) == len(kw)
- assert len(o.rules) == 0
- assert len(o.all_rules) == len(kw)
- for (key, value) in kw.iteritems():
- assert getattr(o, key) == value
- e = raises(ValueError, self.cls, 'my_bytes', length=5, **kw)
- assert str(e) == \
- "Bytes('my_bytes'): cannot mix length with minlength or maxlength"
-
- # Test when minlength or maxlength are less than 1:
- e = raises(ValueError, self.cls, 'my_bytes', minlength=0)
- assert str(e) == "Bytes('my_bytes'): minlength must be >= 1; got 0"
- e = raises(ValueError, self.cls, 'my_bytes', maxlength=0)
- assert str(e) == "Bytes('my_bytes'): maxlength must be >= 1; got 0"
-
- # Test when minlength > maxlength:
- e = raises(ValueError, self.cls, 'my_bytes', minlength=22, maxlength=15)
- assert str(e) == \
- "Bytes('my_bytes'): minlength > maxlength (minlength=22, maxlength=15)"
-
- # Test when minlength == maxlength
- e = raises(ValueError, self.cls, 'my_bytes', minlength=7, maxlength=7)
- assert str(e) == \
- "Bytes('my_bytes'): minlength == maxlength; use length=7 instead"
-
- def test_rule_minlength(self):
- """
- Test the `ipalib.parameter.Bytes._rule_minlength` method.
- """
- name = 'My Bytes'
- o = self.cls('my_bytes', minlength=3)
- assert o.minlength == 3
- m = o._rule_minlength
- translation = u'name=%(name)r, minlength=%(minlength)r'
- dummy = dummy_ugettext(translation)
- assert dummy.translation is translation
-
- # Test with passing values:
- for value in ('abc', 'four', '12345'):
- assert m(dummy, name, value) is None
- assert not hasattr(dummy, 'message')
-
- # Test with a failing value:
- assert_equal(
- m(dummy, name, 'ab'),
- translation % dict(name=name, minlength=3),
- )
- assert dummy.message == \
- '%(name)s must be at least %(minlength)d bytes'
-
- def test_rule_maxlength(self):
- """
- Test the `ipalib.parameter.Bytes._rule_maxlength` method.
- """
- name = 'My Bytes'
- o = self.cls('my_bytes', maxlength=4)
- assert o.maxlength == 4
- m = o._rule_maxlength
- translation = u'name=%(name)r, maxlength=%(maxlength)r'
- dummy = dummy_ugettext(translation)
- assert dummy.translation is translation
-
- # Test with passing values:
- for value in ('ab', '123', 'four'):
- assert m(dummy, name, value) is None
- assert not hasattr(dummy, 'message')
-
- # Test with a failing value:
- assert_equal(
- m(dummy, name, '12345'),
- translation % dict(name=name, maxlength=4),
- )
- assert dummy.message == \
- '%(name)s can be at most %(maxlength)d bytes'
-
- def test_rule_length(self):
- """
- Test the `ipalib.parameter.Bytes._rule_length` method.
- """
- name = 'My Bytes'
- o = self.cls('my_bytes', length=4)
- assert o.length == 4
- m = o._rule_length
- translation = u'name=%(name)r, length=%(length)r'
- dummy = dummy_ugettext(translation)
- assert dummy.translation is translation
-
- # Test with passing values:
- for value in ('1234', 'four'):
- assert m(dummy, name, value) is None
- assert not hasattr(dummy, 'message')
-
- # Test with failing values:
- for value in ('ab', '123', '12345', 'abcdef'):
- assert_equal(
- m(dummy, name, value),
- translation % dict(name=name, length=4),
- )
- assert dummy.message == \
- '%(name)s must be exactly %(length)d bytes'
- dummy = dummy_ugettext(translation)
-
-
-class test_Str(ClassChecker):
- """
- Test the `ipalib.parameter.Str` class.
- """
- _cls = parameter.Str
-
- def test_init(self):
- """
- Test the `ipalib.parameter.Str.__init__` method.
- """
- o = self.cls('my_str')
- assert o.type is unicode
- assert o.minlength is None
- assert o.maxlength is None
- assert o.length is None
- assert o.pattern is None
-
- def test_convert_scalar(self):
- """
- Test the `ipalib.parameter.Str._convert_scalar` method.
- """
- o = self.cls('my_str')
- for value in (u'Hello', 42, 1.2, True):
- assert o._convert_scalar(value) == unicode(value)
- for value in ('Hello', (None,), [u'42', '42'], dict(hello=u'world')):
- e = raises(TypeError, o._convert_scalar, value)
- assert str(e) == \
- 'Can only implicitly convert int, float, or bool; got %r' % value
-
- def test_rule_minlength(self):
- """
- Test the `ipalib.parameter.Str._rule_minlength` method.
- """
- name = 'My Str'
- o = self.cls('my_str', minlength=3)
- assert o.minlength == 3
- m = o._rule_minlength
- translation = u'name=%(name)r, minlength=%(minlength)r'
- dummy = dummy_ugettext(translation)
- assert dummy.translation is translation
-
- # Test with passing values:
- for value in (u'abc', u'four', u'12345'):
- assert m(dummy, name, value) is None
- assert not hasattr(dummy, 'message')
-
- # Test with a failing value:
- assert_equal(
- m(dummy, name, u'ab'),
- translation % dict(name=name, minlength=3),
- )
- assert dummy.message == \
- '%(name)s must be at least %(minlength)d characters'
-
- def test_rule_maxlength(self):
- """
- Test the `ipalib.parameter.Str._rule_maxlength` method.
- """
- name = 'My Str'
- o = self.cls('my_str', maxlength=4)
- assert o.maxlength == 4
- m = o._rule_maxlength
- translation = u'name=%(name)r, maxlength=%(maxlength)r'
- dummy = dummy_ugettext(translation)
- assert dummy.translation is translation
-
- # Test with passing values:
- for value in (u'ab', u'123', u'four'):
- assert m(dummy, name, value) is None
- assert not hasattr(dummy, 'message')
-
- # Test with a failing value:
- assert_equal(
- m(dummy, name, u'12345'),
- translation % dict(name=name, maxlength=4),
- )
- assert dummy.message == \
- '%(name)s can be at most %(maxlength)d characters'
-
- def test_rule_length(self):
- """
- Test the `ipalib.parameter.Str._rule_length` method.
- """
- name = 'My Str'
- o = self.cls('my_str', length=4)
- assert o.length == 4
- m = o._rule_length
- translation = u'name=%(name)r, length=%(length)r'
- dummy = dummy_ugettext(translation)
- assert dummy.translation is translation
-
- # Test with passing values:
- for value in (u'1234', u'four'):
- assert m(dummy, name, value) is None
- assert not hasattr(dummy, 'message')
-
- # Test with failing values:
- for value in (u'ab', u'123', u'12345', u'abcdef'):
- assert_equal(
- m(dummy, name, value),
- translation % dict(name=name, length=4),
- )
- assert dummy.message == \
- '%(name)s must be exactly %(length)d characters'
- dummy = dummy_ugettext(translation)
diff --git a/tests/test_ipalib/test_parameters.py b/tests/test_ipalib/test_parameters.py
new file mode 100644
index 00000000..f9e370fe
--- /dev/null
+++ b/tests/test_ipalib/test_parameters.py
@@ -0,0 +1,944 @@
+# Authors:
+# Jason Gerard DeRose <jderose@redhat.com>
+#
+# Copyright (C) 2008 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; version 2 only
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""
+Test the `ipalib.parameters` module.
+"""
+
+from types import NoneType
+from inspect import isclass
+from tests.util import raises, ClassChecker, read_only
+from tests.util import dummy_ugettext, assert_equal
+from tests.data import binary_bytes, utf8_bytes, unicode_str
+from ipalib import parameters, request, errors2
+from ipalib.constants import TYPE_ERROR, CALLABLE_ERROR, NULLS
+
+
+class test_DefaultFrom(ClassChecker):
+ """
+ Test the `ipalib.parameters.DefaultFrom` class.
+ """
+ _cls = parameters.DefaultFrom
+
+ def test_init(self):
+ """
+ Test the `ipalib.parameters.DefaultFrom.__init__` method.
+ """
+ def callback(*args):
+ return args
+ keys = ('givenname', 'sn')
+ o = self.cls(callback, *keys)
+ assert read_only(o, 'callback') is callback
+ assert read_only(o, 'keys') == keys
+ lam = lambda first, last: first[0] + last
+ o = self.cls(lam)
+ assert read_only(o, 'keys') == ('first', 'last')
+
+ # Test that TypeError is raised when callback isn't callable:
+ e = raises(TypeError, self.cls, 'whatever')
+ assert str(e) == CALLABLE_ERROR % ('callback', 'whatever', str)
+
+ # Test that TypeError is raised when a key isn't an str:
+ e = raises(TypeError, self.cls, callback, 'givenname', 17)
+ assert str(e) == TYPE_ERROR % ('keys', str, 17, int)
+
+ def test_call(self):
+ """
+ Test the `ipalib.parameters.DefaultFrom.__call__` method.
+ """
+ def callback(givenname, sn):
+ return givenname[0] + sn[0]
+ keys = ('givenname', 'sn')
+ o = self.cls(callback, *keys)
+ kw = dict(
+ givenname='John',
+ sn='Public',
+ hello='world',
+ )
+ assert o(**kw) == 'JP'
+ assert o() is None
+ for key in ('givenname', 'sn'):
+ kw_copy = dict(kw)
+ del kw_copy[key]
+ assert o(**kw_copy) is None
+
+ # Test using implied keys:
+ o = self.cls(lambda first, last: first[0] + last)
+ assert o(first='john', last='doe') == 'jdoe'
+ assert o(first='', last='doe') is None
+ assert o(one='john', two='doe') is None
+
+ # Test that co_varnames slice is used:
+ def callback2(first, last):
+ letter = first[0]
+ return letter + last
+ o = self.cls(callback2)
+ assert o.keys == ('first', 'last')
+ assert o(first='john', last='doe') == 'jdoe'
+
+
+def test_parse_param_spec():
+ """
+ Test the `ipalib.parameters.parse_param_spec` function.
+ """
+ f = parameters.parse_param_spec
+ assert f('name') == ('name', dict(required=True, multivalue=False))
+ assert f('name?') == ('name', dict(required=False, multivalue=False))
+ assert f('name*') == ('name', dict(required=False, multivalue=True))
+ assert f('name+') == ('name', dict(required=True, multivalue=True))
+
+ # Make sure other "funny" endings are *not* treated special:
+ assert f('name^') == ('name^', dict(required=True, multivalue=False))
+
+ # Test that TypeError is raised if spec isn't an str:
+ e = raises(TypeError, f, u'name?')
+ assert str(e) == TYPE_ERROR % ('spec', str, u'name?', unicode)
+
+ # Test that ValueError is raised if len(spec) < 2:
+ e = raises(ValueError, f, 'n')
+ assert str(e) == "spec must be at least 2 characters; got 'n'"
+
+
+class DummyRule(object):
+ def __init__(self, error=None):
+ assert error is None or type(error) is unicode
+ self.error = error
+ self.reset()
+
+ def __call__(self, *args):
+ self.calls.append(args)
+ return self.error
+
+ def reset(self):
+ self.calls = []
+
+
+class test_Param(ClassChecker):
+ """
+ Test the `ipalib.parameters.Param` class.
+ """
+ _cls = parameters.Param
+
+ def test_init(self):
+ """
+ Test the `ipalib.parameters.Param.__init__` method.
+ """
+ name = 'my_param'
+ o = self.cls(name)
+ assert o.param_spec is name
+ assert o.name is name
+ assert o.nice == "Param('my_param')"
+ assert o.__islocked__() is True
+
+ # Test default rules:
+ assert o.rules == tuple()
+ assert o.class_rules == tuple()
+ assert o.all_rules == tuple()
+
+ # Test default kwarg values:
+ assert o.cli_name is name
+ assert o.label is None
+ assert o.doc == ''
+ assert o.required is True
+ assert o.multivalue is False
+ assert o.primary_key is False
+ assert o.normalizer is None
+ assert o.default is None
+ assert o.default_from is None
+ assert o.create_default is None
+ assert o._get_default is None
+ assert o.autofill is False
+ assert o.query is False
+ assert o.flags == frozenset()
+
+ # Test that ValueError is raised when a kwarg from a subclass
+ # conflicts with an attribute:
+ class Subclass(self.cls):
+ kwargs = self.cls.kwargs + (
+ ('convert', callable, None),
+ )
+ e = raises(ValueError, Subclass, name)
+ assert str(e) == "kwarg 'convert' conflicts with attribute on Subclass"
+
+ # Test type validation of keyword arguments:
+ class Subclass(self.cls):
+ kwargs = self.cls.kwargs + (
+ ('extra1', bool, True),
+ ('extra2', str, 'Hello'),
+ ('extra3', (int, float), 42),
+ ('extra4', callable, lambda whatever: whatever + 7),
+ )
+ o = Subclass('my_param') # Test with no **kw:
+ for (key, kind, default) in o.kwargs:
+ # Test with a type invalid for all:
+ value = object()
+ kw = {key: value}
+ e = raises(TypeError, Subclass, 'my_param', **kw)
+ if kind is callable:
+ assert str(e) == CALLABLE_ERROR % (key, value, type(value))
+ else:
+ assert str(e) == TYPE_ERROR % (key, kind, value, type(value))
+ # Test with None:
+ kw = {key: None}
+ Subclass('my_param', **kw)
+
+ # Test when using unknown kwargs:
+ e = raises(TypeError, self.cls, 'my_param',
+ flags=['hello', 'world'],
+ whatever=u'Hooray!',
+ )
+ assert str(e) == \
+ "Param('my_param'): takes no such kwargs: 'whatever'"
+ e = raises(TypeError, self.cls, 'my_param', great='Yes', ape='he is!')
+ assert str(e) == \
+ "Param('my_param'): takes no such kwargs: 'ape', 'great'"
+
+ # Test that ValueError is raised if you provide both default_from and
+ # create_default:
+ e = raises(ValueError, self.cls, 'my_param',
+ default_from=lambda first, last: first[0] + last,
+ create_default=lambda **kw: 'The Default'
+ )
+ assert str(e) == '%s: cannot have both %r and %r' % (
+ "Param('my_param')", 'default_from', 'create_default',
+ )
+
+ # Test that _get_default gets set:
+ call1 = lambda first, last: first[0] + last
+ call2 = lambda **kw: 'The Default'
+ o = self.cls('my_param', default_from=call1)
+ assert o.default_from.callback is call1
+ assert o._get_default is o.default_from
+ o = self.cls('my_param', create_default=call2)
+ assert o.create_default is call2
+ assert o._get_default is call2
+
+ def test_repr(self):
+ """
+ Test the `ipalib.parameters.Param.__repr__` method.
+ """
+ for name in ['name', 'name?', 'name*', 'name+']:
+ o = self.cls(name)
+ assert repr(o) == 'Param(%r)' % name
+ o = self.cls('name', required=False)
+ assert repr(o) == "Param('name', required=False)"
+ o = self.cls('name', multivalue=True)
+ assert repr(o) == "Param('name', multivalue=True)"
+
+ def test_clone(self):
+ """
+ Test the `ipalib.parameters.Param.clone` method.
+ """
+ # Test with the defaults
+ orig = self.cls('my_param')
+ clone = orig.clone()
+ assert clone is not orig
+ assert type(clone) is self.cls
+ assert clone.name is orig.name
+ for (key, kind, default) in self.cls.kwargs:
+ assert getattr(clone, key) is getattr(orig, key)
+
+ # Test with a param spec:
+ orig = self.cls('my_param*')
+ assert orig.param_spec == 'my_param*'
+ clone = orig.clone()
+ assert clone.param_spec == 'my_param'
+ assert clone is not orig
+ assert type(clone) is self.cls
+ for (key, kind, default) in self.cls.kwargs:
+ assert getattr(clone, key) is getattr(orig, key)
+
+ # Test with overrides:
+ orig = self.cls('my_param*')
+ assert orig.required is False
+ assert orig.multivalue is True
+ clone = orig.clone(required=True)
+ assert clone is not orig
+ assert type(clone) is self.cls
+ assert clone.required is True
+ assert clone.multivalue is True
+ assert clone.param_spec == 'my_param'
+ assert clone.name == 'my_param'
+
+ def test_get_label(self):
+ """
+ Test the `ipalib.parameters.get_label` method.
+ """
+ context = request.context
+ cli_name = 'the_cli_name'
+ message = 'The Label'
+ label = lambda _: _(message)
+ o = self.cls('name', cli_name=cli_name, label=label)
+ assert o.label is label
+
+ ## Scenario 1: label=callable (a lambda form)
+
+ # Test with no context.ugettext:
+ assert not hasattr(context, 'ugettext')
+ assert_equal(o.get_label(), u'The Label')
+
+ # Test with dummy context.ugettext:
+ assert not hasattr(context, 'ugettext')
+ dummy = dummy_ugettext()
+ context.ugettext = dummy
+ assert o.get_label() is dummy.translation
+ assert dummy.message is message
+ del context.ugettext
+
+ ## Scenario 2: label=None
+ o = self.cls('name', cli_name=cli_name)
+ assert o.label is None
+
+ # Test with no context.ugettext:
+ assert not hasattr(context, 'ugettext')
+ assert_equal(o.get_label(), u'the_cli_name')
+
+ # Test with dummy context.ugettext:
+ assert not hasattr(context, 'ugettext')
+ dummy = dummy_ugettext()
+ context.ugettext = dummy
+ assert_equal(o.get_label(), u'the_cli_name')
+ assert not hasattr(dummy, 'message')
+
+ # Cleanup
+ del context.ugettext
+ assert not hasattr(context, 'ugettext')
+
+ def test_convert(self):
+ """
+ Test the `ipalib.parameters.Param.convert` method.
+ """
+ okay = ('Hello', u'Hello', 0, 4.2, True, False)
+ class Subclass(self.cls):
+ def _convert_scalar(self, value, index=None):
+ return value
+
+ # Test when multivalue=False:
+ o = Subclass('my_param')
+ for value in NULLS:
+ assert o.convert(value) is None
+ for value in okay:
+ assert o.convert(value) is value
+
+ # Test when multivalue=True:
+ o = Subclass('my_param', multivalue=True)
+ for value in NULLS:
+ assert o.convert(value) is None
+ assert o.convert(okay) == okay
+ assert o.convert(NULLS) is None
+ assert o.convert(okay + NULLS) == okay
+ assert o.convert(NULLS + okay) == okay
+ for value in okay:
+ assert o.convert(value) == (value,)
+ assert o.convert([None, value]) == (value,)
+ assert o.convert([value, None]) == (value,)
+
+ def test_convert_scalar(self):
+ """
+ Test the `ipalib.parameters.Param._convert_scalar` method.
+ """
+ dummy = dummy_ugettext()
+
+ # Test with correct type:
+ o = self.cls('my_param')
+ assert o._convert_scalar(None) is None
+ assert dummy.called() is False
+ # Test with incorrect type
+ e = raises(errors2.ConversionError, o._convert_scalar, 'hello', index=17)
+
+ def test_validate(self):
+ """
+ Test the `ipalib.parameters.Param.validate` method.
+ """
+
+ # Test in default state (with no rules, no kwarg):
+ o = self.cls('my_param')
+ e = raises(errors2.RequirementError, o.validate, None)
+ assert e.name == 'my_param'
+
+ # Test with required=False
+ o = self.cls('my_param', required=False)
+ assert o.required is False
+ assert o.validate(None) is None
+
+ # Test with query=True:
+ o = self.cls('my_param', query=True)
+ assert o.query is True
+ assert o.validate(None) is None
+
+ # Test with multivalue=True:
+ o = self.cls('my_param', multivalue=True)
+ e = raises(TypeError, o.validate, [])
+ assert str(e) == TYPE_ERROR % ('value', tuple, [], list)
+ e = raises(ValueError, o.validate, tuple())
+ assert str(e) == 'value: empty tuple must be converted to None'
+
+ # Test with wrong (scalar) type:
+ e = raises(TypeError, o.validate, (None, None, 42, None))
+ assert str(e) == TYPE_ERROR % ('value[2]', NoneType, 42, int)
+ o = self.cls('my_param')
+ e = raises(TypeError, o.validate, 'Hello')
+ assert str(e) == TYPE_ERROR % ('value', NoneType, 'Hello', str)
+
+ class Example(self.cls):
+ type = int
+
+ # Test with some rules and multivalue=False
+ pass1 = DummyRule()
+ pass2 = DummyRule()
+ fail = DummyRule(u'no good')
+ o = Example('example', pass1, pass2)
+ assert o.multivalue is False
+ assert o.validate(11) is None
+ assert pass1.calls == [(request.ugettext, 11)]
+ assert pass2.calls == [(request.ugettext, 11)]
+ pass1.reset()
+ pass2.reset()
+ o = Example('example', pass1, pass2, fail)
+ e = raises(errors2.ValidationError, o.validate, 42)
+ assert e.name == 'example'
+ assert e.error == u'no good'
+ assert e.index is None
+ assert pass1.calls == [(request.ugettext, 42)]
+ assert pass2.calls == [(request.ugettext, 42)]
+ assert fail.calls == [(request.ugettext, 42)]
+
+ # Test with some rules and multivalue=True
+ pass1 = DummyRule()
+ pass2 = DummyRule()
+ fail = DummyRule(u'this one is not good')
+ o = Example('example', pass1, pass2, multivalue=True)
+ assert o.multivalue is True
+ assert o.validate((3, 9)) is None
+ assert pass1.calls == [
+ (request.ugettext, 3),
+ (request.ugettext, 9),
+ ]
+ assert pass2.calls == [
+ (request.ugettext, 3),
+ (request.ugettext, 9),
+ ]
+ pass1.reset()
+ pass2.reset()
+ o = Example('multi_example', pass1, pass2, fail, multivalue=True)
+ assert o.multivalue is True
+ e = raises(errors2.ValidationError, o.validate, (3, 9))
+ assert e.name == 'multi_example'
+ assert e.error == u'this one is not good'
+ assert e.index == 0
+ assert pass1.calls == [(request.ugettext, 3)]
+ assert pass2.calls == [(request.ugettext, 3)]
+ assert fail.calls == [(request.ugettext, 3)]
+
+ def test_validate_scalar(self):
+ """
+ Test the `ipalib.parameters.Param._validate_scalar` method.
+ """
+ class MyParam(self.cls):
+ type = bool
+ okay = DummyRule()
+ o = MyParam('my_param', okay)
+
+ # Test that TypeError is appropriately raised:
+ e = raises(TypeError, o._validate_scalar, 0)
+ assert str(e) == TYPE_ERROR % ('value', bool, 0, int)
+ e = raises(TypeError, o._validate_scalar, 'Hi', index=4)
+ assert str(e) == TYPE_ERROR % ('value[4]', bool, 'Hi', str)
+ e = raises(TypeError, o._validate_scalar, True, index=3.0)
+ assert str(e) == TYPE_ERROR % ('index', int, 3.0, float)
+
+ # Test with passing rule:
+ assert o._validate_scalar(True, index=None) is None
+ assert o._validate_scalar(False, index=None) is None
+ assert okay.calls == [
+ (request.ugettext, True),
+ (request.ugettext, False),
+ ]
+
+ # Test with a failing rule:
+ okay = DummyRule()
+ fail = DummyRule(u'this describes the error')
+ o = MyParam('my_param', okay, fail)
+ e = raises(errors2.ValidationError, o._validate_scalar, True)
+ assert e.name == 'my_param'
+ assert e.error == u'this describes the error'
+ assert e.index is None
+ e = raises(errors2.ValidationError, o._validate_scalar, False, index=2)
+ assert e.name == 'my_param'
+ assert e.error == u'this describes the error'
+ assert e.index == 2
+ assert okay.calls == [
+ (request.ugettext, True),
+ (request.ugettext, False),
+ ]
+ assert fail.calls == [
+ (request.ugettext, True),
+ (request.ugettext, False),
+ ]
+
+ def test_get_default(self):
+ """
+ Test the `ipalib.parameters.Param._get_default` method.
+ """
+ class PassThrough(object):
+ value = None
+
+ def __call__(self, value):
+ assert self.value is None
+ assert value is not None
+ self.value = value
+ return value
+
+ def reset(self):
+ assert self.value is not None
+ self.value = None
+
+ class Str(self.cls):
+ type = unicode
+
+ def __init__(self, name, **kw):
+ self._convert_scalar = PassThrough()
+ super(Str, self).__init__(name, **kw)
+
+ # Test with only a static default:
+ o = Str('my_str',
+ normalizer=PassThrough(),
+ default=u'Static Default',
+ )
+ assert_equal(o.get_default(), u'Static Default')
+ assert o._convert_scalar.value is None
+ assert o.normalizer.value is None
+
+ # Test with default_from:
+ o = Str('my_str',
+ normalizer=PassThrough(),
+ default=u'Static Default',
+ default_from=lambda first, last: first[0] + last,
+ )
+ assert_equal(o.get_default(), u'Static Default')
+ assert o._convert_scalar.value is None
+ assert o.normalizer.value is None
+ default = o.get_default(first=u'john', last='doe')
+ assert_equal(default, u'jdoe')
+ assert o._convert_scalar.value is default
+ assert o.normalizer.value is default
+
+ # Test with create_default:
+ o = Str('my_str',
+ normalizer=PassThrough(),
+ default=u'Static Default',
+ create_default=lambda **kw: u'The created default',
+ )
+ default = o.get_default(first=u'john', last='doe')
+ assert_equal(default, u'The created default')
+ assert o._convert_scalar.value is default
+ assert o.normalizer.value is default
+
+
+class test_Flag(ClassChecker):
+ """
+ Test the `ipalib.parameters.Flag` class.
+ """
+ _cls = parameters.Flag
+
+ def test_init(self):
+ """
+ Test the `ipalib.parameters.Flag.__init__` method.
+ """
+ # Test with no kwargs:
+ o = self.cls('my_flag')
+ assert o.type is bool
+ assert isinstance(o, parameters.Bool)
+ assert o.autofill is True
+ assert o.default is False
+
+ # Test that TypeError is raise if default is not a bool:
+ e = raises(TypeError, self.cls, 'my_flag', default=None)
+ assert str(e) == TYPE_ERROR % ('default', bool, None, NoneType)
+
+ # Test with autofill=False, default=True
+ o = self.cls('my_flag', autofill=False, default=True)
+ assert o.autofill is True
+ assert o.default is True
+
+ # Test when cloning:
+ orig = self.cls('my_flag')
+ for clone in [orig.clone(), orig.clone(autofill=False)]:
+ assert clone.autofill is True
+ assert clone.default is False
+ assert clone is not orig
+ assert type(clone) is self.cls
+
+ # Test when cloning with default=True/False
+ orig = self.cls('my_flag')
+ assert orig.clone().default is False
+ assert orig.clone(default=True).default is True
+ orig = self.cls('my_flag', default=True)
+ assert orig.clone().default is True
+ assert orig.clone(default=False).default is False
+
+
+class test_Data(ClassChecker):
+ """
+ Test the `ipalib.parameters.Data` class.
+ """
+ _cls = parameters.Data
+
+ def test_init(self):
+ """
+ Test the `ipalib.parameters.Data.__init__` method.
+ """
+ o = self.cls('my_data')
+ assert o.type is NoneType
+ assert o.rules == tuple()
+ assert o.class_rules == tuple()
+ assert o.all_rules == tuple()
+ assert o.minlength is None
+ assert o.maxlength is None
+ assert o.length is None
+ assert not hasattr(o, 'pattern')
+
+ # Test mixing length with minlength or maxlength:
+ o = self.cls('my_data', length=5)
+ assert o.length == 5
+ permutations = [
+ dict(minlength=3),
+ dict(maxlength=7),
+ dict(minlength=3, maxlength=7),
+ ]
+ for kw in permutations:
+ o = self.cls('my_data', **kw)
+ for (key, value) in kw.iteritems():
+ assert getattr(o, key) == value
+ e = raises(ValueError, self.cls, 'my_data', length=5, **kw)
+ assert str(e) == \
+ "Data('my_data'): cannot mix length with minlength or maxlength"
+
+ # Test when minlength or maxlength are less than 1:
+ e = raises(ValueError, self.cls, 'my_data', minlength=0)
+ assert str(e) == "Data('my_data'): minlength must be >= 1; got 0"
+ e = raises(ValueError, self.cls, 'my_data', maxlength=0)
+ assert str(e) == "Data('my_data'): maxlength must be >= 1; got 0"
+
+ # Test when minlength > maxlength:
+ e = raises(ValueError, self.cls, 'my_data', minlength=22, maxlength=15)
+ assert str(e) == \
+ "Data('my_data'): minlength > maxlength (minlength=22, maxlength=15)"
+
+ # Test when minlength == maxlength
+ e = raises(ValueError, self.cls, 'my_data', minlength=7, maxlength=7)
+ assert str(e) == \
+ "Data('my_data'): minlength == maxlength; use length=7 instead"
+
+
+class test_Bytes(ClassChecker):
+ """
+ Test the `ipalib.parameters.Bytes` class.
+ """
+ _cls = parameters.Bytes
+
+ def test_init(self):
+ """
+ Test the `ipalib.parameters.Bytes.__init__` method.
+ """
+ o = self.cls('my_bytes')
+ assert o.type is str
+ assert o.rules == tuple()
+ assert o.class_rules == tuple()
+ assert o.all_rules == tuple()
+ assert o.minlength is None
+ assert o.maxlength is None
+ assert o.length is None
+ assert o.pattern is None
+
+ # Test mixing length with minlength or maxlength:
+ o = self.cls('my_bytes', length=5)
+ assert o.length == 5
+ assert len(o.class_rules) == 1
+ assert len(o.rules) == 0
+ assert len(o.all_rules) == 1
+ permutations = [
+ dict(minlength=3),
+ dict(maxlength=7),
+ dict(minlength=3, maxlength=7),
+ ]
+ for kw in permutations:
+ o = self.cls('my_bytes', **kw)
+ assert len(o.class_rules) == len(kw)
+ assert len(o.rules) == 0
+ assert len(o.all_rules) == len(kw)
+ for (key, value) in kw.iteritems():
+ assert getattr(o, key) == value
+ e = raises(ValueError, self.cls, 'my_bytes', length=5, **kw)
+ assert str(e) == \
+ "Bytes('my_bytes'): cannot mix length with minlength or maxlength"
+
+ # Test when minlength or maxlength are less than 1:
+ e = raises(ValueError, self.cls, 'my_bytes', minlength=0)
+ assert str(e) == "Bytes('my_bytes'): minlength must be >= 1; got 0"
+ e = raises(ValueError, self.cls, 'my_bytes', maxlength=0)
+ assert str(e) == "Bytes('my_bytes'): maxlength must be >= 1; got 0"
+
+ # Test when minlength > maxlength:
+ e = raises(ValueError, self.cls, 'my_bytes', minlength=22, maxlength=15)
+ assert str(e) == \
+ "Bytes('my_bytes'): minlength > maxlength (minlength=22, maxlength=15)"
+
+ # Test when minlength == maxlength
+ e = raises(ValueError, self.cls, 'my_bytes', minlength=7, maxlength=7)
+ assert str(e) == \
+ "Bytes('my_bytes'): minlength == maxlength; use length=7 instead"
+
+ def test_rule_minlength(self):
+ """
+ Test the `ipalib.parameters.Bytes._rule_minlength` method.
+ """
+ o = self.cls('my_bytes', minlength=3)
+ assert o.minlength == 3
+ rule = o._rule_minlength
+ translation = u'minlength=%(minlength)r'
+ dummy = dummy_ugettext(translation)
+ assert dummy.translation is translation
+
+ # Test with passing values:
+ for value in ('abc', 'four', '12345'):
+ assert rule(dummy, value) is None
+ assert dummy.called() is False
+
+ # Test with failing values:
+ for value in ('', 'a', '12'):
+ assert_equal(
+ rule(dummy, value),
+ translation % dict(minlength=3)
+ )
+ assert dummy.message == 'must be at least %(minlength)d bytes'
+ assert dummy.called() is True
+ dummy.reset()
+
+ def test_rule_maxlength(self):
+ """
+ Test the `ipalib.parameters.Bytes._rule_maxlength` method.
+ """
+ o = self.cls('my_bytes', maxlength=4)
+ assert o.maxlength == 4
+ rule = o._rule_maxlength
+ translation = u'maxlength=%(maxlength)r'
+ dummy = dummy_ugettext(translation)
+ assert dummy.translation is translation
+
+ # Test with passing values:
+ for value in ('ab', '123', 'four'):
+ assert rule(dummy, value) is None
+ assert dummy.called() is False
+
+ # Test with failing values:
+ for value in ('12345', 'sixsix'):
+ assert_equal(
+ rule(dummy, value),
+ translation % dict(maxlength=4)
+ )
+ assert dummy.message == 'can be at most %(maxlength)d bytes'
+ assert dummy.called() is True
+ dummy.reset()
+
+ def test_rule_length(self):
+ """
+ Test the `ipalib.parameters.Bytes._rule_length` method.
+ """
+ o = self.cls('my_bytes', length=4)
+ assert o.length == 4
+ rule = o._rule_length
+ translation = u'length=%(length)r'
+ dummy = dummy_ugettext(translation)
+ assert dummy.translation is translation
+
+ # Test with passing values:
+ for value in ('1234', 'four'):
+ assert rule(dummy, value) is None
+ assert dummy.called() is False
+
+ # Test with failing values:
+ for value in ('ab', '123', '12345', 'sixsix'):
+ assert_equal(
+ rule(dummy, value),
+ translation % dict(length=4),
+ )
+ assert dummy.message == 'must be exactly %(length)d bytes'
+ assert dummy.called() is True
+ dummy.reset()
+
+
+class test_Str(ClassChecker):
+ """
+ Test the `ipalib.parameters.Str` class.
+ """
+ _cls = parameters.Str
+
+ def test_init(self):
+ """
+ Test the `ipalib.parameters.Str.__init__` method.
+ """
+ o = self.cls('my_str')
+ assert o.type is unicode
+ assert o.minlength is None
+ assert o.maxlength is None
+ assert o.length is None
+ assert o.pattern is None
+
+ def test_convert_scalar(self):
+ """
+ Test the `ipalib.parameters.Str._convert_scalar` method.
+ """
+ o = self.cls('my_str')
+ mthd = o._convert_scalar
+ for value in (u'Hello', 42, 1.2):
+ assert mthd(value) == unicode(value)
+ for value in [True, 'Hello', (u'Hello',), [42.3], dict(one=1)]:
+ e = raises(errors2.ConversionError, mthd, value)
+ assert e.name == 'my_str'
+ assert e.index is None
+ assert_equal(e.error, u'must be Unicode text')
+ e = raises(errors2.ConversionError, mthd, value, index=18)
+ assert e.name == 'my_str'
+ assert e.index == 18
+ assert_equal(e.error, u'must be Unicode text')
+
+ def test_rule_minlength(self):
+ """
+ Test the `ipalib.parameters.Str._rule_minlength` method.
+ """
+ o = self.cls('my_str', minlength=3)
+ assert o.minlength == 3
+ rule = o._rule_minlength
+ translation = u'minlength=%(minlength)r'
+ dummy = dummy_ugettext(translation)
+ assert dummy.translation is translation
+
+ # Test with passing values:
+ for value in (u'abc', u'four', u'12345'):
+ assert rule(dummy, value) is None
+ assert dummy.called() is False
+
+ # Test with failing values:
+ for value in (u'', u'a', u'12'):
+ assert_equal(
+ rule(dummy, value),
+ translation % dict(minlength=3)
+ )
+ assert dummy.message == 'must be at least %(minlength)d characters'
+ assert dummy.called() is True
+ dummy.reset()
+
+ def test_rule_maxlength(self):
+ """
+ Test the `ipalib.parameters.Str._rule_maxlength` method.
+ """
+ o = self.cls('my_str', maxlength=4)
+ assert o.maxlength == 4
+ rule = o._rule_maxlength
+ translation = u'maxlength=%(maxlength)r'
+ dummy = dummy_ugettext(translation)
+ assert dummy.translation is translation
+
+ # Test with passing values:
+ for value in (u'ab', u'123', u'four'):
+ assert rule(dummy, value) is None
+ assert dummy.called() is False
+
+ # Test with failing values:
+ for value in (u'12345', u'sixsix'):
+ assert_equal(
+ rule(dummy, value),
+ translation % dict(maxlength=4)
+ )
+ assert dummy.message == 'can be at most %(maxlength)d characters'
+ assert dummy.called() is True
+ dummy.reset()
+
+ def test_rule_length(self):
+ """
+ Test the `ipalib.parameters.Str._rule_length` method.
+ """
+ o = self.cls('my_str', length=4)
+ assert o.length == 4
+ rule = o._rule_length
+ translation = u'length=%(length)r'
+ dummy = dummy_ugettext(translation)
+ assert dummy.translation is translation
+
+ # Test with passing values:
+ for value in (u'1234', u'four'):
+ assert rule(dummy, value) is None
+ assert dummy.called() is False
+
+ # Test with failing values:
+ for value in (u'ab', u'123', u'12345', u'sixsix'):
+ assert_equal(
+ rule(dummy, value),
+ translation % dict(length=4),
+ )
+ assert dummy.message == 'must be exactly %(length)d characters'
+ assert dummy.called() is True
+ dummy.reset()
+
+
+def test_create_param():
+ """
+ Test the `ipalib.parameters.create_param` function.
+ """
+ f = parameters.create_param
+
+ # Test that Param instances are returned unchanged:
+ params = (
+ parameters.Param('one?'),
+ parameters.Int('two+'),
+ parameters.Str('three*'),
+ parameters.Bytes('four'),
+ )
+ for p in params:
+ assert f(p) is p
+
+ # Test that the spec creates an Str instance:
+ for spec in ('one?', 'two+', 'three*', 'four'):
+ (name, kw) = parameters.parse_param_spec(spec)
+ p = f(spec)
+ assert p.param_spec is spec
+ assert p.name == name
+ assert p.required is kw['required']
+ assert p.multivalue is kw['multivalue']
+
+ # Test that TypeError is raised when spec is neither a Param nor a str:
+ for spec in (u'one', 42, parameters.Param, parameters.Str):
+ e = raises(TypeError, f, spec)
+ assert str(e) == \
+ TYPE_ERROR % ('spec', (str, parameters.Param), spec, type(spec))
+
+
+def test_messages():
+ """
+ Test module level message in `ipalib.parameters`.
+ """
+ for name in dir(parameters):
+ if name.startswith('_'):
+ continue
+ attr = getattr(parameters, name)
+ if not (isclass(attr) and issubclass(attr, parameters.Param)):
+ continue
+ assert type(attr.type_error) is str
+ assert attr.type_error in parameters.__messages
diff --git a/tests/util.py b/tests/util.py
index 3033b82b..af4c2393 100644
--- a/tests/util.py
+++ b/tests/util.py
@@ -28,6 +28,7 @@ import tempfile
import shutil
import ipalib
from ipalib.plugable import Plugin
+from ipalib.request import context
@@ -202,6 +203,14 @@ class ClassChecker(object):
'get_subcls()'
)
+ def tearDown(self):
+ """
+ nose tear-down fixture.
+ """
+ for name in ('ugettext', 'ungettext'):
+ if hasattr(context, name):
+ delattr(context, name)
+
@@ -297,12 +306,24 @@ class dummy_ugettext(object):
assert type(self.translation) is unicode
def __call__(self, message):
- assert type(message) is str
assert self.__called is False
self.__called = True
+ assert type(message) is str
+ assert not hasattr(self, 'message')
self.message = message
+ assert type(self.translation) is unicode
return self.translation
+ def called(self):
+ return self.__called
+
+ def reset(self):
+ assert type(self.translation) is unicode
+ assert type(self.message) is str
+ del self.message
+ assert self.__called is True
+ self.__called = False
+
class dummy_ungettext(object):
__called = False