summaryrefslogtreecommitdiffstats
path: root/tests/test_ipalib/test_frontend.py
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2009-01-22 10:42:41 -0500
committerRob Crittenden <rcritten@redhat.com>2009-01-22 10:42:41 -0500
commitc2967a675a288e7d31374229fd974d0cb9966f2c (patch)
tree58be8ca6319f4660d9f18b97a37b9c0c56104d02 /tests/test_ipalib/test_frontend.py
parent2b8b87b4d6c3b4389a0a7bf48c225035c53e7ad1 (diff)
parent5d82e3b35a8fb2d4c25f282cddad557a7650197c (diff)
downloadfreeipa.git-c2967a675a288e7d31374229fd974d0cb9966f2c.tar.gz
freeipa.git-c2967a675a288e7d31374229fd974d0cb9966f2c.tar.xz
freeipa.git-c2967a675a288e7d31374229fd974d0cb9966f2c.zip
Merge branch 'master' of git://fedorapeople.org/~jderose/freeipa2
Diffstat (limited to 'tests/test_ipalib/test_frontend.py')
-rw-r--r--tests/test_ipalib/test_frontend.py771
1 files changed, 771 insertions, 0 deletions
diff --git a/tests/test_ipalib/test_frontend.py b/tests/test_ipalib/test_frontend.py
new file mode 100644
index 00000000..071a70fd
--- /dev/null
+++ b/tests/test_ipalib/test_frontend.py
@@ -0,0 +1,771 @@
+# 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.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 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():
+ assert frontend.RULE_FLAG == 'validation_rule'
+
+
+def test_rule():
+ """
+ Test the `ipalib.frontend.rule` function.
+ """
+ flag = frontend.RULE_FLAG
+ rule = frontend.rule
+ def my_func():
+ pass
+ assert not hasattr(my_func, flag)
+ rule(my_func)
+ assert getattr(my_func, flag) is True
+ @rule
+ def my_func2():
+ pass
+ assert getattr(my_func2, flag) is True
+
+
+def test_is_rule():
+ """
+ Test the `ipalib.frontend.is_rule` function.
+ """
+ is_rule = frontend.is_rule
+ flag = frontend.RULE_FLAG
+
+ class no_call(object):
+ def __init__(self, value):
+ if value is not None:
+ assert value in (True, False)
+ setattr(self, flag, value)
+
+ class call(no_call):
+ def __call__(self):
+ pass
+
+ assert is_rule(call(True))
+ assert not is_rule(no_call(True))
+ assert not is_rule(call(False))
+ assert not is_rule(call(None))
+
+
+class test_Command(ClassChecker):
+ """
+ Test the `ipalib.frontend.Command` class.
+ """
+
+ _cls = frontend.Command
+
+ def get_subcls(self):
+ """
+ Return a standard subclass of `ipalib.frontend.Command`.
+ """
+ class Rule(object):
+ def __init__(self, name):
+ self.name = name
+
+ def __call__(self, _, value):
+ if value != self.name:
+ return _('must equal %r') % self.name
+
+ default_from = parameters.DefaultFrom(
+ lambda arg: arg,
+ 'default_from'
+ )
+ normalizer = lambda value: value.lower()
+
+ class example(self.cls):
+ takes_options = (
+ parameters.Str('option0', Rule('option0'),
+ normalizer=normalizer,
+ default_from=default_from,
+ ),
+ parameters.Str('option1', Rule('option1'),
+ normalizer=normalizer,
+ default_from=default_from,
+ ),
+ )
+ return example
+
+ def get_instance(self, args=tuple(), options=tuple()):
+ """
+ Helper method used to test args and options.
+ """
+ class example(self.cls):
+ takes_args = args
+ takes_options = options
+ o = example()
+ o.finalize()
+ return o
+
+ def test_class(self):
+ """
+ Test the `ipalib.frontend.Command` class.
+ """
+ assert self.cls.__bases__ == (plugable.Plugin,)
+ assert self.cls.takes_options == tuple()
+ assert self.cls.takes_args == tuple()
+
+ def test_get_args(self):
+ """
+ Test the `ipalib.frontend.Command.get_args` method.
+ """
+ assert list(self.cls().get_args()) == []
+ args = ('login', 'stuff')
+ o = self.get_instance(args=args)
+ assert o.get_args() is args
+
+ def test_get_options(self):
+ """
+ Test the `ipalib.frontend.Command.get_options` method.
+ """
+ assert list(self.cls().get_options()) == []
+ options = ('verbose', 'debug')
+ o = self.get_instance(options=options)
+ assert o.get_options() is options
+
+ def test_args(self):
+ """
+ Test the ``ipalib.frontend.Command.args`` instance attribute.
+ """
+ assert 'args' in self.cls.__public__ # Public
+ assert self.cls().args is None
+ o = self.cls()
+ o.finalize()
+ assert type(o.args) is plugable.NameSpace
+ assert len(o.args) == 0
+ args = ('destination', 'source?')
+ ns = self.get_instance(args=args).args
+ assert type(ns) is plugable.NameSpace
+ assert len(ns) == len(args)
+ assert list(ns) == ['destination', 'source']
+ 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
+ assert ns.source.multivalue is False
+
+ # Test TypeError:
+ e = raises(TypeError, self.get_instance, args=(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'))
+ assert str(e) == 'arg2: required argument after optional'
+
+ # Test ValueError, scalar after multivalue:
+ e = raises(ValueError, self.get_instance, args=('arg1+', 'arg2'))
+ assert str(e) == 'arg2: only final argument can be multivalue'
+
+ def test_max_args(self):
+ """
+ Test the ``ipalib.frontend.Command.max_args`` instance attribute.
+ """
+ o = self.get_instance()
+ assert o.max_args == 0
+ o = self.get_instance(args=('one?',))
+ assert o.max_args == 1
+ o = self.get_instance(args=('one', 'two?'))
+ assert o.max_args == 2
+ o = self.get_instance(args=('one', 'multi+',))
+ assert o.max_args is None
+ o = self.get_instance(args=('one', 'multi*',))
+ assert o.max_args is None
+
+ def test_options(self):
+ """
+ Test the ``ipalib.frontend.Command.options`` instance attribute.
+ """
+ assert 'options' in self.cls.__public__ # Public
+ assert self.cls().options is None
+ o = self.cls()
+ o.finalize()
+ assert type(o.options) is plugable.NameSpace
+ assert len(o.options) == 0
+ options = ('target', 'files*')
+ ns = self.get_instance(options=options).options
+ assert type(ns) is plugable.NameSpace
+ assert len(ns) == len(options)
+ assert list(ns) == ['target', 'files']
+ 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
+ assert ns.files.multivalue is True
+
+ def test_convert(self):
+ """
+ Test the `ipalib.frontend.Command.convert` method.
+ """
+ assert 'convert' in self.cls.__public__ # Public
+ kw = dict(
+ option0=u'1.5',
+ option1=u'7',
+ )
+ o = self.subcls()
+ o.finalize()
+ for (key, value) in o.convert(**kw).iteritems():
+ assert_equal(unicode(kw[key]), value)
+
+ def test_normalize(self):
+ """
+ Test the `ipalib.frontend.Command.normalize` method.
+ """
+ assert 'normalize' in self.cls.__public__ # Public
+ kw = dict(
+ option0=u'OPTION0',
+ option1=u'OPTION1',
+ )
+ norm = dict((k, v.lower()) for (k, v) in kw.items())
+ sub = self.subcls()
+ sub.finalize()
+ assert sub.normalize(**kw) == norm
+
+ def test_get_default(self):
+ """
+ Test the `ipalib.frontend.Command.get_default` method.
+ """
+ assert 'get_default' in self.cls.__public__ # Public
+ # FIXME: Add an updated unit tests for get_default()
+
+ def test_validate(self):
+ """
+ Test the `ipalib.frontend.Command.validate` method.
+ """
+ assert 'validate' in self.cls.__public__ # Public
+
+ sub = self.subcls()
+ sub.finalize()
+
+ # Check with valid values
+ okay = dict(
+ option0=u'option0',
+ option1=u'option1',
+ another_option='some value',
+ )
+ sub.validate(**okay)
+
+ # Check with an invalid value
+ fail = dict(okay)
+ fail['option0'] = u'whatever'
+ 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
+
+ # Check with a missing required arg
+ fail = dict(okay)
+ fail.pop('option1')
+ e = raises(errors.RequirementError, sub.validate, **fail)
+ assert e.name == 'option1'
+ assert e.value is None
+ assert e.index is None
+
+ def test_execute(self):
+ """
+ Test the `ipalib.frontend.Command.execute` method.
+ """
+ assert 'execute' in self.cls.__public__ # Public
+ o = self.cls()
+ e = raises(NotImplementedError, o.execute)
+ assert str(e) == 'Command.execute()'
+
+ def test_args_to_kw(self):
+ """
+ Test the `ipalib.frontend.Command.args_to_kw` method.
+ """
+ assert 'args_to_kw' in self.cls.__public__ # Public
+ o = self.get_instance(args=('one', 'two?'))
+ assert o.args_to_kw(1) == dict(one=1)
+ assert o.args_to_kw(1, 2) == dict(one=1, two=2)
+
+ o = self.get_instance(args=('one', 'two*'))
+ assert o.args_to_kw(1) == dict(one=1)
+ assert o.args_to_kw(1, 2) == dict(one=1, two=(2,))
+ assert o.args_to_kw(1, 2, 3) == dict(one=1, two=(2, 3))
+
+ o = self.get_instance(args=('one', 'two+'))
+ assert o.args_to_kw(1) == dict(one=1)
+ assert o.args_to_kw(1, 2) == dict(one=1, two=(2,))
+ assert o.args_to_kw(1, 2, 3) == dict(one=1, two=(2, 3))
+
+ o = self.get_instance()
+ e = raises(errors.ArgumentError, o.args_to_kw, 1)
+ assert str(e) == 'example takes no arguments'
+
+ o = self.get_instance(args=('one?',))
+ e = raises(errors.ArgumentError, o.args_to_kw, 1, 2)
+ assert str(e) == 'example takes at most 1 argument'
+
+ o = self.get_instance(args=('one', 'two?'))
+ e = raises(errors.ArgumentError, o.args_to_kw, 1, 2, 3)
+ assert str(e) == 'example takes at most 2 arguments'
+
+ def test_params_2_args_options(self):
+ """
+ Test the `ipalib.frontend.Command.params_2_args_options` method.
+ """
+ assert 'params_2_args_options' in self.cls.__public__ # Public
+ o = self.get_instance(args=['one'], options=['two'])
+ assert o.params_2_args_options({}) == ((None,), dict(two=None))
+ assert o.params_2_args_options(dict(one=1)) == ((1,), dict(two=None))
+ assert o.params_2_args_options(dict(two=2)) == ((None,), dict(two=2))
+ assert o.params_2_args_options(dict(two=2, one=1)) == \
+ ((1,), dict(two=2))
+
+ def test_run(self):
+ """
+ Test the `ipalib.frontend.Command.run` method.
+ """
+ class my_cmd(self.cls):
+ def execute(self, *args, **kw):
+ return ('execute', args, kw)
+
+ def forward(self, *args, **kw):
+ return ('forward', args, kw)
+
+ args = ('Hello,', 'world,')
+ kw = dict(how_are='you', on_this='fine day?')
+
+ # Test in server context:
+ (api, home) = create_test_api(in_server=True)
+ api.finalize()
+ o = my_cmd()
+ o.set_api(api)
+ assert o.run.im_func is self.cls.run.im_func
+ assert ('execute', args, kw) == o.run(*args, **kw)
+ assert o.run.im_func is my_cmd.execute.im_func
+
+ # Test in non-server context
+ (api, home) = create_test_api(in_server=False)
+ api.finalize()
+ o = my_cmd()
+ o.set_api(api)
+ assert o.run.im_func is self.cls.run.im_func
+ assert ('forward', args, kw) == o.run(*args, **kw)
+ assert o.run.im_func is my_cmd.forward.im_func
+
+
+class test_LocalOrRemote(ClassChecker):
+ """
+ Test the `ipalib.frontend.LocalOrRemote` class.
+ """
+ _cls = frontend.LocalOrRemote
+
+ def test_init(self):
+ """
+ Test the `ipalib.frontend.LocalOrRemote.__init__` method.
+ """
+ o = self.cls()
+ o.finalize()
+ assert list(o.args) == []
+ assert list(o.options) == ['server']
+ op = o.options.server
+ assert op.required is False
+ assert op.default is False
+
+ def test_run(self):
+ """
+ Test the `ipalib.frontend.LocalOrRemote.run` method.
+ """
+ class example(self.cls):
+ takes_args = ['key?']
+
+ def forward(self, *args, **options):
+ return ('forward', args, options)
+
+ def execute(self, *args, **options):
+ return ('execute', args, options)
+
+ # Test when in_server=False:
+ (api, home) = create_test_api(in_server=False)
+ api.register(example)
+ api.finalize()
+ cmd = api.Command.example
+ assert cmd() == ('execute', (None,), dict(server=False))
+ assert cmd(u'var') == ('execute', (u'var',), dict(server=False))
+ assert cmd(server=True) == ('forward', (None,), dict(server=True))
+ assert cmd(u'var', server=True) == \
+ ('forward', (u'var',), dict(server=True))
+
+ # Test when in_server=True (should always call execute):
+ (api, home) = create_test_api(in_server=True)
+ api.register(example)
+ api.finalize()
+ cmd = api.Command.example
+ assert cmd() == ('execute', (None,), dict(server=False))
+ assert cmd(u'var') == ('execute', (u'var',), dict(server=False))
+ assert cmd(server=True) == ('execute', (None,), dict(server=True))
+ assert cmd(u'var', server=True) == \
+ ('execute', (u'var',), dict(server=True))
+
+
+class test_Object(ClassChecker):
+ """
+ Test the `ipalib.frontend.Object` class.
+ """
+ _cls = frontend.Object
+
+ def test_class(self):
+ """
+ Test the `ipalib.frontend.Object` class.
+ """
+ assert self.cls.__bases__ == (plugable.Plugin,)
+ assert self.cls.backend is None
+ assert self.cls.methods is None
+ assert self.cls.properties is None
+ assert self.cls.params is None
+ assert self.cls.params_minus_pk is None
+ assert self.cls.takes_params == tuple()
+
+ def test_init(self):
+ """
+ Test the `ipalib.frontend.Object.__init__` method.
+ """
+ o = self.cls()
+ assert o.backend is None
+ assert o.methods is None
+ assert o.properties is None
+ assert o.params is None
+ assert o.params_minus_pk is None
+ assert o.properties is None
+
+ def test_set_api(self):
+ """
+ Test the `ipalib.frontend.Object.set_api` method.
+ """
+ # Setup for test:
+ class DummyAttribute(object):
+ def __init__(self, obj_name, attr_name, name=None):
+ self.obj_name = obj_name
+ self.attr_name = attr_name
+ if name is None:
+ self.name = '%s_%s' % (obj_name, attr_name)
+ else:
+ self.name = name
+ self.param = frontend.create_param(attr_name)
+
+ def __clone__(self, attr_name):
+ return self.__class__(
+ self.obj_name,
+ self.attr_name,
+ getattr(self, attr_name)
+ )
+
+ def get_attributes(cnt, format):
+ for name in ['other', 'user', 'another']:
+ for i in xrange(cnt):
+ yield DummyAttribute(name, format % i)
+
+ cnt = 10
+ formats = dict(
+ methods='method_%d',
+ properties='property_%d',
+ )
+
+
+ _d = dict(
+ Method=plugable.NameSpace(
+ get_attributes(cnt, formats['methods'])
+ ),
+ Property=plugable.NameSpace(
+ get_attributes(cnt, formats['properties'])
+ ),
+ )
+ api = plugable.MagicDict(_d)
+ assert len(api.Method) == cnt * 3
+ assert len(api.Property) == cnt * 3
+
+ class user(self.cls):
+ pass
+
+ # Actually perform test:
+ o = user()
+ o.set_api(api)
+ assert read_only(o, 'api') is api
+ for name in ['methods', 'properties']:
+ namespace = getattr(o, name)
+ assert isinstance(namespace, plugable.NameSpace)
+ assert len(namespace) == cnt
+ f = formats[name]
+ for i in xrange(cnt):
+ attr_name = f % i
+ attr = namespace[attr_name]
+ assert isinstance(attr, DummyAttribute)
+ assert attr is getattr(namespace, attr_name)
+ assert attr.obj_name == 'user'
+ assert attr.attr_name == attr_name
+ assert attr.name == attr_name
+
+ # Test params instance attribute
+ o = self.cls()
+ o.set_api(api)
+ ns = o.params
+ assert type(ns) is plugable.NameSpace
+ assert len(ns) == 0
+ class example(self.cls):
+ takes_params = ('banana', 'apple')
+ o = example()
+ o.set_api(api)
+ ns = o.params
+ assert type(ns) is plugable.NameSpace
+ assert len(ns) == 2, repr(ns)
+ assert list(ns) == ['banana', 'apple']
+ for p in ns():
+ assert type(p) is parameters.Str
+ assert p.required is True
+ assert p.multivalue is False
+
+ def test_primary_key(self):
+ """
+ Test the `ipalib.frontend.Object.primary_key` attribute.
+ """
+ (api, home) = create_test_api()
+ api.finalize()
+
+ # Test with no primary keys:
+ class example1(self.cls):
+ takes_params = (
+ 'one',
+ 'two',
+ )
+ o = example1()
+ o.set_api(api)
+ assert o.primary_key is None
+ assert o.params_minus_pk is None
+
+ # Test with 1 primary key:
+ class example2(self.cls):
+ takes_params = (
+ 'one',
+ 'two',
+ parameters.Str('three', primary_key=True),
+ 'four',
+ )
+ o = example2()
+ o.set_api(api)
+ pk = o.primary_key
+ assert type(pk) is parameters.Str
+ assert pk.name == 'three'
+ assert pk.primary_key is True
+ assert o.params[2] is o.primary_key
+ assert isinstance(o.params_minus_pk, plugable.NameSpace)
+ assert list(o.params_minus_pk) == ['one', 'two', 'four']
+
+ # Test with multiple primary_key:
+ class example3(self.cls):
+ takes_params = (
+ parameters.Str('one', primary_key=True),
+ parameters.Str('two', primary_key=True),
+ 'three',
+ parameters.Str('four', primary_key=True),
+ )
+ o = example3()
+ e = raises(ValueError, o.set_api, api)
+ assert str(e) == \
+ 'example3 (Object) has multiple primary keys: one, two, four'
+
+ def test_backend(self):
+ """
+ Test the `ipalib.frontend.Object.backend` attribute.
+ """
+ (api, home) = create_test_api()
+ class ldap(backend.Backend):
+ whatever = 'It worked!'
+ api.register(ldap)
+ class user(frontend.Object):
+ backend_name = 'ldap'
+ api.register(user)
+ api.finalize()
+ b = api.Object.user.backend
+ assert isinstance(b, ldap)
+ assert b.whatever == 'It worked!'
+
+ def test_get_dn(self):
+ """
+ Test the `ipalib.frontend.Object.get_dn` method.
+ """
+ assert 'get_dn' in self.cls.__public__ # Public
+ o = self.cls()
+ e = raises(NotImplementedError, o.get_dn, 'primary key')
+ assert str(e) == 'Object.get_dn()'
+ class user(self.cls):
+ pass
+ o = user()
+ e = raises(NotImplementedError, o.get_dn, 'primary key')
+ assert str(e) == 'user.get_dn()'
+
+
+class test_Attribute(ClassChecker):
+ """
+ Test the `ipalib.frontend.Attribute` class.
+ """
+ _cls = frontend.Attribute
+
+ def test_class(self):
+ """
+ Test the `ipalib.frontend.Attribute` class.
+ """
+ assert self.cls.__bases__ == (plugable.Plugin,)
+ assert type(self.cls.obj) is property
+ assert type(self.cls.obj_name) is property
+ assert type(self.cls.attr_name) is property
+
+ def test_init(self):
+ """
+ Test the `ipalib.frontend.Attribute.__init__` method.
+ """
+ class user_add(self.cls):
+ pass
+ o = user_add()
+ assert read_only(o, 'obj') is None
+ assert read_only(o, 'obj_name') == 'user'
+ assert read_only(o, 'attr_name') == 'add'
+
+ def test_set_api(self):
+ """
+ Test the `ipalib.frontend.Attribute.set_api` method.
+ """
+ user_obj = 'The user frontend.Object instance'
+ class api(object):
+ Object = dict(user=user_obj)
+ class user_add(self.cls):
+ pass
+ o = user_add()
+ assert read_only(o, 'api') is None
+ assert read_only(o, 'obj') is None
+ o.set_api(api)
+ assert read_only(o, 'api') is api
+ assert read_only(o, 'obj') is user_obj
+
+
+class test_Method(ClassChecker):
+ """
+ Test the `ipalib.frontend.Method` class.
+ """
+ _cls = frontend.Method
+
+ def test_class(self):
+ """
+ Test the `ipalib.frontend.Method` class.
+ """
+ assert self.cls.__bases__ == (frontend.Attribute, frontend.Command)
+ assert self.cls.implements(frontend.Command)
+ assert self.cls.implements(frontend.Attribute)
+
+ def test_init(self):
+ """
+ Test the `ipalib.frontend.Method.__init__` method.
+ """
+ class user_add(self.cls):
+ pass
+ o = user_add()
+ assert o.name == 'user_add'
+ assert o.obj_name == 'user'
+ assert o.attr_name == 'add'
+ assert frontend.Command.implemented_by(o)
+ assert frontend.Attribute.implemented_by(o)
+
+
+class test_Property(ClassChecker):
+ """
+ Test the `ipalib.frontend.Property` class.
+ """
+ _cls = frontend.Property
+
+ def get_subcls(self):
+ """
+ Return a standard subclass of `ipalib.frontend.Property`.
+ """
+ class user_givenname(self.cls):
+ 'User first name'
+
+ @frontend.rule
+ def rule0_lowercase(self, value):
+ if not value.islower():
+ return 'Must be lowercase'
+ return user_givenname
+
+ def test_class(self):
+ """
+ Test the `ipalib.frontend.Property` class.
+ """
+ assert self.cls.__bases__ == (frontend.Attribute,)
+ assert self.cls.klass is parameters.Str
+
+ def test_init(self):
+ """
+ Test the `ipalib.frontend.Property.__init__` method.
+ """
+ o = self.subcls()
+ assert len(o.rules) == 1
+ assert o.rules[0].__name__ == 'rule0_lowercase'
+ param = o.param
+ assert isinstance(param, parameters.Str)
+ assert param.name == 'givenname'
+ assert param.doc == 'User first name'
+
+
+class test_Application(ClassChecker):
+ """
+ Test the `ipalib.frontend.Application` class.
+ """
+ _cls = frontend.Application
+
+ def test_class(self):
+ """
+ Test the `ipalib.frontend.Application` class.
+ """
+ assert self.cls.__bases__ == (frontend.Command,)
+ assert type(self.cls.application) is property
+
+ def test_application(self):
+ """
+ Test the `ipalib.frontend.Application.application` property.
+ """
+ assert 'application' in self.cls.__public__ # Public
+ assert 'set_application' in self.cls.__public__ # Public
+ app = 'The external application'
+ class example(self.cls):
+ 'A subclass'
+ for o in (self.cls(), example()):
+ assert read_only(o, 'application') is None
+ e = raises(TypeError, o.set_application, None)
+ assert str(e) == (
+ '%s.application cannot be None' % o.__class__.__name__
+ )
+ o.set_application(app)
+ assert read_only(o, 'application') is app
+ e = raises(AttributeError, o.set_application, app)
+ assert str(e) == (
+ '%s.application can only be set once' % o.__class__.__name__
+ )
+ assert read_only(o, 'application') is app