Fuzzy feelings

This commit is contained in:
Jason Gerard DeRose 2009-12-17 06:16:18 -07:00 committed by Rob Crittenden
parent c3f9ec14d9
commit 29f243bf4e
8 changed files with 690 additions and 432 deletions

View File

@ -21,6 +21,7 @@
Test the `tests.util` module. Test the `tests.util` module.
""" """
import re
import util import util
from util import raises, TYPE, VALUE, LEN, KEYS from util import raises, TYPE, VALUE, LEN, KEYS
@ -48,12 +49,99 @@ class Prop(object):
prop = property(__get_prop, __set_prop, __del_prop) prop = property(__get_prop, __set_prop, __del_prop)
class test_Fuzzy(object):
klass = util.Fuzzy
def test_init(self):
inst = self.klass()
assert inst.regex is None
assert inst.type is None
assert inst.test is None
assert inst.re is None
inst = self.klass('(foo|bar)')
assert inst.regex == '(foo|bar)'
assert inst.type is unicode
assert inst.test is None
assert isinstance(inst.re, re._pattern_type)
inst = self.klass('(foo|bar)', type=str)
assert inst.regex == '(foo|bar)'
assert inst.type is str
assert inst.test is None
assert isinstance(inst.re, re._pattern_type)
t = lambda other: other > 500
inst = self.klass(test=t)
assert inst.regex is None
assert inst.type is None
assert inst.test is t
assert inst.re is None
inst = self.klass(type=(int, float), test=t)
assert inst.regex is None
assert inst.type == (int, float)
assert inst.test is t
assert inst.re is None
def test_repr(self):
s = 'Fuzzy(regex=%r, type=%r, test=%r)'
t = lambda other: 0.0 <= other <= 1.0
inst = self.klass()
assert repr(inst) == s % (None, None, None)
inst = self.klass('foo')
assert repr(inst) == s % ('foo', unicode, None)
inst = self.klass(type=(int, float))
assert repr(inst) == s % (None, (int, float), None)
inst = self.klass(type=(int, float), test=t)
assert repr(inst) == s % (None, (int, float), t)
inst = self.klass(test=t)
assert repr(inst) == s % (None, None, t)
def test_eq(self):
assert (self.klass('bar') == u'foobar') is True
assert (self.klass('^bar') == u'foobar') is False
assert (self.klass('bar', type=str) == u'foobar') is False
assert ('18' == self.klass()) is True
assert ('18' == self.klass(type=int)) is False
assert (18 == self.klass(type=int)) is True
assert ('18' == self.klass(type=(int, str))) is True
assert (self.klass() == '18') is True
assert (self.klass(type=int) == '18') is False
assert (self.klass(type=int) == 18) is True
assert (self.klass(type=(int, str)) == '18') is True
t = lambda other: other.endswith('bar')
assert (self.klass(test=t) == 'foobar') is True
assert (self.klass(test=t, type=unicode) == 'foobar') is False
assert (self.klass(test=t) == 'barfoo') is False
assert (False == self.klass()) is True
assert (True == self.klass()) is True
assert (None == self.klass()) is True
def test_assert_deepequal(): def test_assert_deepequal():
f = util.assert_deepequal f = util.assert_deepequal
# Test with good scalar values: # Test with good scalar values:
f(u'hello', u'hello', 'foo') f(u'hello', u'hello')
f(18, 18, 'foo') f(util.Fuzzy(), u'hello')
f(util.Fuzzy(type=unicode), u'hello')
f(util.Fuzzy('ell'), u'hello')
f(util.Fuzzy(test=lambda other: other.endswith('llo')), u'hello')
f(18, 18)
f(util.Fuzzy(), 18)
f(util.Fuzzy(type=int), 18)
f(util.Fuzzy(type=(int, float), test=lambda other: other > 17.9), 18)
# Test with bad scalar values: # Test with bad scalar values:
e = raises(AssertionError, f, u'hello', u'world', 'foo') e = raises(AssertionError, f, u'hello', u'world', 'foo')

View File

@ -21,20 +21,41 @@
Defines the expected objectclass for various entries. Defines the expected objectclass for various entries.
""" """
host = ( user = [
u'top',
u'person',
u'organizationalperson',
u'inetorgperson',
u'inetuser',
u'posixaccount',
u'krbprincipalaux',
u'radiusprofile',
u'ipaobject',
]
group = [
u'top',
u'groupofnames',
u'nestedgroup',
u'ipausergroup',
u'ipaobject',
]
host = [
u'ipaobject', u'ipaobject',
u'nshost', u'nshost',
u'ipahost', u'ipahost',
u'pkiuser', u'pkiuser',
u'ipaservice',
u'krbprincipalaux', u'krbprincipalaux',
u'krbprincipal', u'krbprincipal',
u'top', u'top',
) ]
hostgroup = ( hostgroup = [
u'ipaobject', u'ipaobject',
u'ipahostgroup', u'ipahostgroup',
u'nestedGroup', u'nestedGroup',
u'groupOfNames', u'groupOfNames',
u'top', u'top',
) ]

View File

@ -21,248 +21,331 @@
Test the `ipalib/plugins/group.py` module. Test the `ipalib/plugins/group.py` module.
""" """
import sys
from xmlrpc_test import XMLRPC_test, assert_attr_equal
from ipalib import api, errors from ipalib import api, errors
from xmlrpc_test import Declarative from tests.test_xmlrpc import objectclasses
from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid
group1 = u'testgroup1'
group_objectclass = ( group2 = u'testgroup2'
u'top',
u'groupofnames',
u'nestedgroup',
u'ipausergroup',
u'ipaobject',
)
class test_group(Declarative): class test_group(Declarative):
cleanup_commands = [ cleanup_commands = [
('group_del', [u'testgroup1'], {}), ('group_del', [group1], {}),
('group_del', [u'testgroup2'], {}), ('group_del', [group2], {}),
] ]
tests = [ tests = [
# testgroup1:
################
# create group1:
dict( dict(
desc='Try to retrieve a non-existant testgroup1', desc='Try to retrieve non-existant %r' % group1,
command=('group_show', [u'testgroup2'], {}), command=('group_show', [group1], {}),
expected=errors.NotFound(reason='no such entry'), expected=errors.NotFound(reason='no such entry'),
), ),
dict(
desc='Create testgroup1',
command=(
'group_add', [u'testgroup1'], dict(description=u'Test desc 1')
),
expected=dict(
value=u'testgroup1',
result=dict(
cn=(u'testgroup1',),
description=(u'Test desc 1',),
objectclass=group_objectclass,
),
summary=u'Added group "testgroup1"',
),
ignore_values=['ipauniqueid', 'dn'],
),
dict( dict(
desc='Try to create testgroup1 again', desc='Try to update non-existant %r' % group1,
command=('group_mod', [group1], dict(description=u'Foo')),
expected=errors.NotFound(reason='no such entry'),
),
dict(
desc='Try to delete non-existant %r' % group1,
command=('group_del', [group1], {}),
expected=errors.NotFound(reason='no such entry'),
),
dict(
desc='Create %r' % group1,
command=( command=(
'group_add', [u'testgroup1'], dict(description=u'Test desc 1') 'group_add', [group1], dict(description=u'Test desc 1')
),
expected=dict(
value=group1,
summary=u'Added group "testgroup1"',
result=dict(
cn=[group1],
description=[u'Test desc 1'],
objectclass=objectclasses.group,
ipauniqueid=[fuzzy_uuid],
dn=u'cn=testgroup1,cn=groups,cn=accounts,' + api.env.basedn,
),
),
),
dict(
desc='Try to create duplicate %r' % group1,
command=(
'group_add', [group1], dict(description=u'Test desc 1')
), ),
expected=errors.DuplicateEntry(), expected=errors.DuplicateEntry(),
), ),
dict(
desc='Retrieve testgroup1',
command=('group_show', [u'testgroup1'], {}),
expected=dict(
value=u'testgroup1',
result=dict(
cn=(u'testgroup1',),
description=(u'Test desc 1',),
),
summary=None,
),
ignore_values=['dn'],
),
dict( dict(
desc='Updated testgroup1', desc='Retrieve %r' % group1,
command=('group_show', [group1], {}),
expected=dict(
value=group1,
summary=None,
result=dict(
cn=[group1],
description=[u'Test desc 1'],
dn=u'cn=testgroup1,cn=groups,cn=accounts,' + api.env.basedn,
),
),
),
dict(
desc='Updated %r' % group1,
command=( command=(
'group_mod', [u'testgroup1'], dict(description=u'New desc 1') 'group_mod', [group1], dict(description=u'New desc 1')
), ),
expected=dict( expected=dict(
result=dict( result=dict(
description=(u'New desc 1',), description=[u'New desc 1'],
), ),
summary=u'Modified group "testgroup1"', summary=u'Modified group "testgroup1"',
value=u'testgroup1', value=group1,
), ),
), ),
dict( dict(
desc='Retrieve testgroup1 to check update', desc='Retrieve %r to verify update' % group1,
command=('group_show', [u'testgroup1'], {}), command=('group_show', [group1], {}),
expected=dict( expected=dict(
value=u'testgroup1', value=group1,
result=dict( result=dict(
cn=(u'testgroup1',), cn=[group1],
description=(u'New desc 1',), description=[u'New desc 1'],
dn=u'cn=testgroup1,cn=groups,cn=accounts,' + api.env.basedn,
), ),
summary=None, summary=None,
), ),
ignore_values=['dn'],
), ),
# FIXME: The return value is totally different here than from the above # FIXME: The return value is totally different here than from the above
# group_mod() test. I think that for all *_mod() commands we should # group_mod() test. I think that for all *_mod() commands we should
# just return the entry exactly as *_show() does. # just return the entry exactly as *_show() does.
dict( dict(
desc='Updated testgroup1 to promote it to posix group', desc='Updated %r to promote it to a posix group' % group1,
command=('group_mod', [u'testgroup1'], dict(posix=True)), command=('group_mod', [group1], dict(posix=True)),
expected=dict( expected=dict(
result=dict( result=dict(
cn=(u'testgroup1',), cn=[group1],
description=(u'New desc 1',), description=[u'New desc 1'],
objectclass=group_objectclass + (u'posixgroup',), objectclass=objectclasses.group + [u'posixgroup'],
ipauniqueid=[fuzzy_uuid],
gidnumber=[fuzzy_digits],
), ),
value=u'testgroup1', value=group1,
summary=u'Modified group "testgroup1"', summary=u'Modified group "testgroup1"',
), ),
ignore_values=['gidnumber', 'ipauniqueid'],
), ),
dict( dict(
desc="Retrieve testgroup1 to check it's a posix group", desc="Retrieve %r to verify it's a posix group" % group1,
command=('group_show', [u'testgroup1'], {}), command=('group_show', [group1], {}),
expected=dict( expected=dict(
value=u'testgroup1', value=group1,
result=dict( result=dict(
cn=(u'testgroup1',), cn=[group1],
description=(u'New desc 1',), description=(u'New desc 1',),
dn=u'cn=testgroup1,cn=groups,cn=accounts,' + api.env.basedn,
gidnumber=[fuzzy_digits],
), ),
summary=None, summary=None,
), ),
ignore_values=['dn', 'gidnumber'],
), ),
dict( dict(
desc='Search for testgroup1', desc='Search for %r' % group1,
command=('group_find', [], dict(cn=u'testgroup1')), command=('group_find', [], dict(cn=group1)),
expected=dict( expected=dict(
count=1, count=1,
truncated=False, truncated=False,
result=( result=[
dict( dict(
cn=(u'testgroup1',), cn=[group1],
description=(u'New desc 1',), description=[u'New desc 1'],
gidnumber=[fuzzy_digits],
), ),
), ],
summary=u'1 group matched', summary=u'1 group matched',
), ),
ignore_values=['gidnumber'],
), ),
# testgroup2:
################
# create group2:
dict( dict(
desc='Try to retrieve a non-existant testgroup2', desc='Try to retrieve non-existant %r' % group2,
command=('group_show', [u'testgroup2'], {}), command=('group_show', [group2], {}),
expected=errors.NotFound(reason='no such entry'), expected=errors.NotFound(reason='no such entry'),
), ),
dict(
desc='Create testgroup2',
command=(
'group_add', [u'testgroup2'], dict(description=u'Test desc 2')
),
expected=dict(
value=u'testgroup2',
result=dict(
cn=(u'testgroup2',),
description=(u'Test desc 2',),
objectclass=group_objectclass,
),
summary=u'Added group "testgroup2"',
),
ignore_values=['ipauniqueid', 'dn'],
),
dict( dict(
desc='Try to create testgroup2 again', desc='Try to update non-existant %r' % group2,
command=('group_mod', [group2], dict(description=u'Foo')),
expected=errors.NotFound(reason='no such entry'),
),
dict(
desc='Try to delete non-existant %r' % group2,
command=('group_del', [group2], {}),
expected=errors.NotFound(reason='no such entry'),
),
dict(
desc='Create %r' % group2,
command=( command=(
'group_add', [u'testgroup2'], dict(description=u'Test desc 2') 'group_add', [group2], dict(description=u'Test desc 2')
),
expected=dict(
value=group2,
summary=u'Added group "testgroup2"',
result=dict(
cn=[group2],
description=[u'Test desc 2'],
objectclass=objectclasses.group,
ipauniqueid=[fuzzy_uuid],
dn=u'cn=testgroup2,cn=groups,cn=accounts,' + api.env.basedn,
),
),
),
dict(
desc='Try to create duplicate %r' % group2,
command=(
'group_add', [group2], dict(description=u'Test desc 2')
), ),
expected=errors.DuplicateEntry(), expected=errors.DuplicateEntry(),
), ),
dict( dict(
desc='Retrieve testgroup2', desc='Retrieve %r' % group2,
command=('group_show', [u'testgroup2'], {}), command=('group_show', [group2], {}),
expected=dict( expected=dict(
value=u'testgroup2', value=group2,
summary=None,
result=dict( result=dict(
cn=(u'testgroup2',), cn=[group2],
description=(u'Test desc 2',), description=[u'Test desc 2'],
dn=u'cn=testgroup2,cn=groups,cn=accounts,' + api.env.basedn,
),
),
),
dict(
desc='Updated %r' % group2,
command=(
'group_mod', [group2], dict(description=u'New desc 2')
),
expected=dict(
result=dict(
description=[u'New desc 2'],
),
summary=u'Modified group "testgroup2"',
value=group2,
),
),
dict(
desc='Retrieve %r to verify update' % group2,
command=('group_show', [group2], {}),
expected=dict(
value=group2,
result=dict(
cn=[group2],
description=[u'New desc 2'],
dn=u'cn=testgroup2,cn=groups,cn=accounts,' + api.env.basedn,
), ),
summary=None, summary=None,
), ),
ignore_values=['dn'],
), ),
dict( dict(
desc='Search for testgroup2', desc='Search for %r' % group2,
command=('group_find', [], dict(cn=u'testgroup2')), command=('group_find', [], dict(cn=group2)),
expected=dict( expected=dict(
count=1, count=1,
truncated=False, truncated=False,
result=( result=[
dict( dict(
cn=(u'testgroup2',), cn=[group2],
description=(u'Test desc 2',), description=[u'New desc 2'],
), ),
), ],
summary=u'1 group matched', summary=u'1 group matched',
), ),
), ),
dict( dict(
desc='Updated testgroup2', desc='Search for all groups',
command=( command=('group_find', [], {}),
'group_mod', [u'testgroup2'], dict(description=u'New desc 2')
),
expected=dict( expected=dict(
result=dict( summary=u'5 groups matched',
description=(u'New desc 2',), count=5,
), truncated=False,
value=u'testgroup2', result=[
summary=u'Modified group "testgroup2"', {
'member user': [u'admin'],
'gidnumber': [fuzzy_digits],
'cn': [u'admins'],
'description': [u'Account administrators group'],
},
{
'gidnumber': [fuzzy_digits],
'cn': [u'ipausers'],
'description': [u'Default group for all users'],
},
{
'gidnumber': [fuzzy_digits],
'cn': [u'editors'],
'description': [u'Limited admins who can edit other users'],
},
dict(
cn=[group1],
description=[u'New desc 1'],
gidnumber=[fuzzy_digits],
),
dict(
cn=[group2],
description=[u'New desc 2'],
),
],
), ),
), ),
dict(
desc='Retrieve testgroup2 to check update',
command=('group_show', [u'testgroup2'], {}),
expected=dict(
value=u'testgroup2',
result=dict(
cn=(u'testgroup2',),
description=(u'New desc 2',),
),
summary=None,
),
ignore_values=['dn'],
),
###############
# member stuff: # member stuff:
dict( dict(
desc='Make testgroup2 member of testgroup1', desc='Add member %r to %r' % (group2, group1),
command=( command=(
'group_add_member', [u'testgroup1'], dict(group=u'testgroup2') 'group_add_member', [group1], dict(group=group2)
), ),
expected=dict( expected=dict(
completed=1, completed=1,
@ -272,15 +355,15 @@ class test_group(Declarative):
user=tuple(), user=tuple(),
), ),
), ),
result={'member group': (u'testgroup2',)}, result={'member group': (group2,)},
), ),
), ),
dict( dict(
# FIXME: Shouldn't this raise a NotFound instead? # FIXME: Shouldn't this raise a NotFound instead?
desc='Try to add a non-existent member to testgroup1', desc='Try to add non-existent member to %r' % group1,
command=( command=(
'group_add_member', [u'testgroup1'], dict(group=u'notfound') 'group_add_member', [group1], dict(group=u'notfound')
), ),
expected=dict( expected=dict(
completed=0, completed=0,
@ -290,14 +373,14 @@ class test_group(Declarative):
user=tuple(), user=tuple(),
), ),
), ),
result={'member group': (u'testgroup2',)}, result={'member group': (group2,)},
), ),
), ),
dict( dict(
desc='Remove member testgroup2 from testgroup1', desc='Remove member %r from %r' % (group2, group1),
command=('group_remove_member', command=('group_remove_member',
[u'testgroup1'], dict(group=u'testgroup2') [group1], dict(group=group2)
), ),
expected=dict( expected=dict(
completed=1, completed=1,
@ -313,9 +396,9 @@ class test_group(Declarative):
dict( dict(
# FIXME: Shouldn't this raise a NotFound instead? # FIXME: Shouldn't this raise a NotFound instead?
desc='Try to remove a non-existent member from testgroup1', desc='Try to remove non-existent member from %r' % group1,
command=('group_remove_member', command=('group_remove_member',
[u'testgroup1'], dict(group=u'notfound') [group1], dict(group=u'notfound')
), ),
expected=dict( expected=dict(
completed=0, completed=0,
@ -330,69 +413,73 @@ class test_group(Declarative):
), ),
# Delete:
################
# delete group1:
dict( dict(
desc='Delete testgroup1', desc='Delete %r' % group1,
command=('group_del', [u'testgroup1'], {}), command=('group_del', [group1], {}),
expected=dict( expected=dict(
result=True, result=True,
value=u'testgroup1', value=group1,
summary=u'Deleted group "testgroup1"', summary=u'Deleted group "testgroup1"',
), )
), ),
dict( dict(
desc='Delete testgroup2', desc='Try to delete non-existant %r' % group1,
command=('group_del', [u'testgroup2'], {}), command=('group_del', [group1], {}),
expected=errors.NotFound(reason='no such entry'),
),
dict(
desc='Try to retrieve non-existant %r' % group1,
command=('group_show', [group1], {}),
expected=errors.NotFound(reason='no such entry'),
),
dict(
desc='Try to update non-existant %r' % group1,
command=('group_mod', [group1], dict(description=u'Foo')),
expected=errors.NotFound(reason='no such entry'),
),
################
# delete group2:
dict(
desc='Delete %r' % group2,
command=('group_del', [group2], {}),
expected=dict( expected=dict(
result=True, result=True,
value=u'testgroup2', value=group2,
summary=u'Deleted group "testgroup2"', summary=u'Deleted group "testgroup2"',
), )
), ),
##############
# Non-existent
##############
# testgroup1:
dict( dict(
desc='Try to retrieve non-existent testgroup1', desc='Try to delete non-existant %r' % group2,
command=('group_show', [u'testgroup1'], {}), command=('group_del', [group2], {}),
expected=errors.NotFound(reason='no such entry'),
),
dict(
desc='Try to update non-existent testgroup1',
command=(
'group_mod', [u'testgroup1'], dict(description=u'New desc 1')
),
expected=errors.NotFound(reason='no such entry'),
),
dict(
desc='Try to delete non-existent testgroup1',
command=('group_del', [u'testgroup1'], {}),
expected=errors.NotFound(reason='no such entry'), expected=errors.NotFound(reason='no such entry'),
), ),
# testgroup2:
dict( dict(
desc='Try to retrieve non-existent testgroup2', desc='Try to retrieve non-existant %r' % group2,
command=('group_show', [u'testgroup2'], {}), command=('group_show', [group2], {}),
expected=errors.NotFound(reason='no such entry'),
),
dict(
desc='Try to update non-existent testgroup2',
command=(
'group_mod', [u'testgroup2'], dict(description=u'New desc 2')
),
expected=errors.NotFound(reason='no such entry'),
),
dict(
desc='Try to delete non-existent testgroup2',
command=('group_del', [u'testgroup2'], {}),
expected=errors.NotFound(reason='no such entry'), expected=errors.NotFound(reason='no such entry'),
), ),
dict(
desc='Try to update non-existant %r' % group2,
command=('group_mod', [group2], dict(description=u'Foo')),
expected=errors.NotFound(reason='no such entry'),
),
] ]

View File

@ -23,11 +23,12 @@ Test the `ipalib.plugins.host` module.
""" """
from ipalib import api, errors from ipalib import api, errors
from tests.test_xmlrpc.xmlrpc_test import Declarative from tests.test_xmlrpc.xmlrpc_test import Declarative, fuzzy_uuid
from tests.test_xmlrpc import objectclasses from tests.test_xmlrpc import objectclasses
fqdn1 = u'testhost1.%s' % api.env.domain fqdn1 = u'testhost1.%s' % api.env.domain
dn1 = u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn1, api.env.basedn)
class test_host(Declarative): class test_host(Declarative):
@ -71,16 +72,18 @@ class test_host(Declarative):
value=fqdn1, value=fqdn1,
summary=u'Added host "%s"' % fqdn1, summary=u'Added host "%s"' % fqdn1,
result=dict( result=dict(
cn=(fqdn1,), # FIXME: we should only return fqdn dn=dn1,
fqdn=(fqdn1,), cn=[fqdn1], # FIXME: we should only return fqdn
description=(u'Test host 1',), fqdn=[fqdn1],
localityname=(u'Undisclosed location 1',), description=[u'Test host 1'],
krbprincipalname=(u'host/%s@%s' % (fqdn1, api.env.realm),), localityname=[u'Undisclosed location 1'],
serverhostname=(u'testhost1',), krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
serverhostname=[u'testhost1'],
objectclass=objectclasses.host, objectclass=objectclasses.host,
managedby=[dn1],
ipauniqueid=[fuzzy_uuid],
), ),
), ),
ignore_values=['ipauniqueid', 'dn'],
), ),
@ -103,12 +106,12 @@ class test_host(Declarative):
value=fqdn1, value=fqdn1,
summary=None, summary=None,
result=dict( result=dict(
fqdn=(fqdn1,), dn=dn1,
description=(u'Test host 1',), fqdn=[fqdn1],
localityname=(u'Undisclosed location 1',), description=[u'Test host 1'],
localityname=[u'Undisclosed location 1'],
), ),
), ),
ignore_values=['dn'],
), ),
@ -119,20 +122,22 @@ class test_host(Declarative):
value=fqdn1, value=fqdn1,
summary=None, summary=None,
result=dict( result=dict(
cn=(fqdn1,), dn=dn1,
fqdn=(fqdn1,), cn=[fqdn1],
description=(u'Test host 1',), fqdn=[fqdn1],
description=[u'Test host 1'],
# FIXME: Why is 'localalityname' returned as 'l' with --all? # FIXME: Why is 'localalityname' returned as 'l' with --all?
# It is intuitive for --all to return additional attributes, # It is intuitive for --all to return additional attributes,
# but not to return existing attributes under different # but not to return existing attributes under different
# names. # names.
l=(u'Undisclosed location 1',), l=[u'Undisclosed location 1'],
krbprincipalname=(u'host/%s@%s' % (fqdn1, api.env.realm),), krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
serverhostname=(u'testhost1',), serverhostname=[u'testhost1'],
objectclass=objectclasses.host, objectclass=objectclasses.host,
managedby=[dn1],
ipauniqueid=[fuzzy_uuid],
), ),
), ),
ignore_values=['dn', 'ipauniqueid'],
), ),
@ -143,13 +148,13 @@ class test_host(Declarative):
count=1, count=1,
truncated=False, truncated=False,
summary=u'1 host matched', summary=u'1 host matched',
result=( result=[
dict( dict(
fqdn=(fqdn1,), fqdn=[fqdn1],
description=(u'Test host 1',), description=[u'Test host 1'],
localityname=(u'Undisclosed location 1',), localityname=[u'Undisclosed location 1'],
), ),
), ],
), ),
), ),
@ -161,25 +166,24 @@ class test_host(Declarative):
count=1, count=1,
truncated=False, truncated=False,
summary=u'1 host matched', summary=u'1 host matched',
result=( result=[
dict( dict(
cn=(fqdn1,), cn=[fqdn1],
fqdn=(fqdn1,), fqdn=[fqdn1],
description=(u'Test host 1',), description=[u'Test host 1'],
# FIXME: Why is 'localalityname' returned as 'l' with --all? # FIXME: Why is 'localalityname' returned as 'l' with --all?
# It is intuitive for --all to return additional attributes, # It is intuitive for --all to return additional attributes,
# but not to return existing attributes under different # but not to return existing attributes under different
# names. # names.
l=(u'Undisclosed location 1',), l=[u'Undisclosed location 1'],
krbprincipalname=(u'host/%s@%s' % (fqdn1, api.env.realm),), krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
serverhostname=(u'testhost1',), serverhostname=[u'testhost1'],
objectclass=objectclasses.host, objectclass=objectclasses.host,
managedby=[dn1],
ipauniqueid=[fuzzy_uuid],
), ),
), ],
), ),
# FIXME: With --all, host_show() returns the 'dn', but host_find()
# doesn't.
ignore_values=['ipauniqueid'],
), ),
@ -190,7 +194,7 @@ class test_host(Declarative):
value=fqdn1, value=fqdn1,
summary=u'Modified host "%s"' % fqdn1, summary=u'Modified host "%s"' % fqdn1,
result=dict( result=dict(
description=(u'Updated host 1',), description=[u'Updated host 1'],
), ),
), ),
), ),
@ -203,12 +207,12 @@ class test_host(Declarative):
value=fqdn1, value=fqdn1,
summary=None, summary=None,
result=dict( result=dict(
fqdn=(fqdn1,), dn=dn1,
description=(u'Updated host 1',), fqdn=[fqdn1],
localityname=(u'Undisclosed location 1',), description=[u'Updated host 1'],
localityname=[u'Undisclosed location 1'],
), ),
), ),
ignore_values=['dn'],
), ),

View File

@ -23,32 +23,35 @@ Test the `ipalib.plugins.hostgroup` module.
""" """
from ipalib import api, errors from ipalib import api, errors
from tests.test_xmlrpc.xmlrpc_test import Declarative from tests.test_xmlrpc.xmlrpc_test import Declarative, fuzzy_uuid
from tests.test_xmlrpc import objectclasses from tests.test_xmlrpc import objectclasses
hostgroup1 = u'testhostgroup1'
dn1 = u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup1, api.env.basedn)
fqdn1 = u'testhost1.%s' % api.env.domain fqdn1 = u'testhost1.%s' % api.env.domain
host_dn1 = u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn1, api.env.basedn)
class test_hostgroup(Declarative): class test_hostgroup(Declarative):
cleanup_commands = [ cleanup_commands = [
('hostgroup_del', [u'testhostgroup1'], {}), ('hostgroup_del', [hostgroup1], {}),
('host_del', [fqdn1], {}), ('host_del', [fqdn1], {}),
] ]
tests=[ tests=[
dict( dict(
desc='Try to retrieve non-existent testhostgroup1', desc='Try to retrieve non-existent %r' % hostgroup1,
command=('hostgroup_show', [u'testhostgroup1'], {}), command=('hostgroup_show', [hostgroup1], {}),
expected=errors.NotFound(reason='no such entry'), expected=errors.NotFound(reason='no such entry'),
), ),
dict( dict(
desc='Try to update non-existent testhostgroup1', desc='Try to update non-existent %r' % hostgroup1,
command=('hostgroup_mod', [u'testhostgroup1'], command=('hostgroup_mod', [hostgroup1],
dict(description=u'Updated hostgroup 1') dict(description=u'Updated hostgroup 1')
), ),
expected=errors.NotFound(reason='no such entry'), expected=errors.NotFound(reason='no such entry'),
@ -56,33 +59,34 @@ class test_hostgroup(Declarative):
dict( dict(
desc='Try to delete non-existent testhostgroup1', desc='Try to delete non-existent %r' % hostgroup1,
command=('hostgroup_del', [u'testhostgroup1'], {}), command=('hostgroup_del', [hostgroup1], {}),
expected=errors.NotFound(reason='no such entry'), expected=errors.NotFound(reason='no such entry'),
), ),
dict( dict(
desc='Create hostgroup testhostgroup1', desc='Create %r' % hostgroup1,
command=('hostgroup_add', [u'testhostgroup1'], command=('hostgroup_add', [hostgroup1],
dict(description=u'Test hostgroup 1') dict(description=u'Test hostgroup 1')
), ),
expected=dict( expected=dict(
value=u'testhostgroup1', value=hostgroup1,
summary=u'Added hostgroup "testhostgroup1"', summary=u'Added hostgroup "testhostgroup1"',
result=dict( result=dict(
cn=(u'testhostgroup1',), dn=dn1,
cn=[hostgroup1],
objectclass=objectclasses.hostgroup, objectclass=objectclasses.hostgroup,
description=(u'Test hostgroup 1',), description=[u'Test hostgroup 1'],
ipauniqueid=[fuzzy_uuid],
), ),
), ),
ignore_values=['ipauniqueid', 'dn'],
), ),
dict( dict(
desc='Try to create duplicate testhostgroup1', desc='Try to create duplicate %r' % hostgroup1,
command=('hostgroup_add', [u'testhostgroup1'], command=('hostgroup_add', [hostgroup1],
dict(description=u'Test hostgroup 1') dict(description=u'Test hostgroup 1')
), ),
expected=errors.DuplicateEntry(), expected=errors.DuplicateEntry(),
@ -101,23 +105,25 @@ class test_hostgroup(Declarative):
value=fqdn1, value=fqdn1,
summary=u'Added host "%s"' % fqdn1, summary=u'Added host "%s"' % fqdn1,
result=dict( result=dict(
cn=(fqdn1,), # FIXME: we should only return fqdn dn=host_dn1,
fqdn=(fqdn1,), cn=[fqdn1], # FIXME: we should only return fqdn
description=(u'Test host 1',), fqdn=[fqdn1],
localityname=(u'Undisclosed location 1',), description=[u'Test host 1'],
krbprincipalname=(u'host/%s@%s' % (fqdn1, api.env.realm),), localityname=[u'Undisclosed location 1'],
serverhostname=(u'testhost1',), krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
serverhostname=[u'testhost1'],
objectclass=objectclasses.host, objectclass=objectclasses.host,
managedby=[host_dn1],
ipauniqueid=[fuzzy_uuid],
), ),
), ),
ignore_values=['ipauniqueid', 'dn'],
), ),
dict( dict(
desc=u'Add %r to testhostgroup1' % fqdn1, desc=u'Add host %r to %r' % (fqdn1, hostgroup1),
command=( command=(
'hostgroup_add_member', [u'testhostgroup1'], dict(host=fqdn1) 'hostgroup_add_member', [hostgroup1], dict(host=fqdn1)
), ),
expected=dict( expected=dict(
completed=1, completed=1,
@ -128,80 +134,80 @@ class test_hostgroup(Declarative):
), ),
), ),
result={ result={
'member host': (fqdn1,), 'member host': [fqdn1],
}, },
), ),
), ),
dict( dict(
desc='Retrieve testhostgroup1', desc='Retrieve %r' % hostgroup1,
command=('hostgroup_show', [u'testhostgroup1'], {}), command=('hostgroup_show', [hostgroup1], {}),
expected=dict( expected=dict(
value=u'testhostgroup1', value=hostgroup1,
summary=None, summary=None,
result={ result={
'member host': (u'testhost1.example.com',), 'dn': dn1,
'cn': (u'testhostgroup1',), 'member host': [u'testhost1.example.com'],
'description': (u'Test hostgroup 1',) 'cn': [hostgroup1],
'description': [u'Test hostgroup 1'],
}, },
), ),
ignore_values=['dn'],
), ),
dict( dict(
desc='Search for testhostgroup1', desc='Search for %r' % hostgroup1,
command=('hostgroup_find', [], dict(cn=u'testhostgroup1')), command=('hostgroup_find', [], dict(cn=hostgroup1)),
expected=dict( expected=dict(
count=1, count=1,
truncated=False, truncated=False,
summary=u'1 hostgroup matched', summary=u'1 hostgroup matched',
result=( result=[
{ {
'member host': (u'testhost1.example.com',), 'member host': [u'testhost1.example.com'],
'cn': (u'testhostgroup1',), 'cn': [hostgroup1],
'description': (u'Test hostgroup 1',), 'description': [u'Test hostgroup 1'],
}, },
), ],
), ),
), ),
dict( dict(
desc='Update testhostgroup1', desc='Update %r' % hostgroup1,
command=('hostgroup_mod', [u'testhostgroup1'], command=('hostgroup_mod', [hostgroup1],
dict(description=u'Updated hostgroup 1') dict(description=u'Updated hostgroup 1')
), ),
expected=dict( expected=dict(
value=u'testhostgroup1', value=hostgroup1,
summary=u'Modified hostgroup "testhostgroup1"', summary=u'Modified hostgroup "testhostgroup1"',
result=dict( result=dict(
description=(u'Updated hostgroup 1',), description=[u'Updated hostgroup 1'],
), ),
), ),
), ),
dict( dict(
desc='Retrieve testhostgroup1 to verify update', desc='Retrieve %r to verify update' % hostgroup1,
command=('hostgroup_show', [u'testhostgroup1'], {}), command=('hostgroup_show', [hostgroup1], {}),
expected=dict( expected=dict(
value=u'testhostgroup1', value=hostgroup1,
summary=None, summary=None,
result={ result={
'member host': (u'testhost1.example.com',), 'dn': dn1,
'cn': (u'testhostgroup1',), 'member host': [u'testhost1.example.com'],
'description': (u'Updated hostgroup 1',) 'cn': [hostgroup1],
'description': [u'Updated hostgroup 1'],
}, },
), ),
ignore_values=['dn'],
), ),
dict( dict(
desc='Remove %s from testhostgroup1', desc='Remove host %r from %r' % (fqdn1, hostgroup1),
command=('hostgroup_remove_member', [u'testhostgroup1'], command=('hostgroup_remove_member', [hostgroup1],
dict(host=fqdn1) dict(host=fqdn1)
), ),
expected=dict( expected=dict(
@ -218,10 +224,10 @@ class test_hostgroup(Declarative):
dict( dict(
desc='Delete testhostgroup1', desc='Delete %r' % hostgroup1,
command=('hostgroup_del', [u'testhostgroup1'], {}), command=('hostgroup_del', [hostgroup1], {}),
expected=dict( expected=dict(
value=u'testhostgroup1', value=hostgroup1,
summary=u'Deleted hostgroup "testhostgroup1"', summary=u'Deleted hostgroup "testhostgroup1"',
result=True, result=True,
), ),
@ -229,7 +235,7 @@ class test_hostgroup(Declarative):
dict( dict(
desc='Delete %s' % fqdn1, desc='Delete host %r' % fqdn1,
command=('host_del', [fqdn1], {}), command=('host_del', [fqdn1], {}),
expected=dict( expected=dict(
value=fqdn1, value=fqdn1,

View File

@ -24,66 +24,71 @@ Test the `ipalib/plugins/user.py` module.
""" """
from ipalib import api, errors from ipalib import api, errors
from xmlrpc_test import Declarative from tests.test_xmlrpc import objectclasses
from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid
user_objectclass = (
u'top',
u'person',
u'organizationalperson',
u'inetorgperson',
u'inetuser',
u'posixaccount',
u'krbprincipalaux',
u'radiusprofile',
u'ipaobject',
)
user_memberof = (u'cn=ipausers,cn=groups,cn=accounts,dc=example,dc=com',) user_memberof = (u'cn=ipausers,cn=groups,cn=accounts,dc=example,dc=com',)
user1=u'tuser1'
class test_user(Declarative): class test_user(Declarative):
cleanup_commands = [ cleanup_commands = [
('user_del', [u'tuser1'], {}), ('user_del', [user1], {}),
] ]
tests = [ tests = [
dict( dict(
desc='Try to retrieve non-existant user', desc='Try to retrieve non-existent %r' % user1,
command=( command=('user_show', [user1], {}),
'user_show', [u'tuser1'], {}
),
expected=errors.NotFound(reason='no such entry'), expected=errors.NotFound(reason='no such entry'),
), ),
dict( dict(
desc='Create a user', desc='Try to update non-existent %r' % user1,
command=( command=('user_mod', [user1], dict(givenname=u'Foo')),
'user_add', [], dict(givenname=u'Test', sn=u'User1') expected=errors.NotFound(reason='no such entry'),
),
expected=dict(
value=u'tuser1',
result=dict(
cn=(u'Test User1',),
gecos=(u'tuser1',),
givenname=(u'Test',),
homedirectory=(u'/home/tuser1',),
krbprincipalname=(u'tuser1@' + api.env.realm,),
loginshell=(u'/bin/sh',),
objectclass=user_objectclass,
sn=(u'User1',),
uid=(u'tuser1',),
),
summary=u'Added user "tuser1"',
),
ignore_values=['ipauniqueid', 'gidnumber', 'dn'],
), ),
dict( dict(
desc='Try to create another user with same login', desc='Try to delete non-existent %r' % user1,
command=('user_del', [user1], {}),
expected=errors.NotFound(reason='no such entry'),
),
dict(
desc='Create %r' % user1,
command=(
'user_add', [], dict(givenname=u'Test', sn=u'User1')
),
expected=dict(
value=user1,
summary=u'Added user "tuser1"',
result=dict(
cn=[u'Test User1'],
gecos=[user1],
givenname=[u'Test'],
homedirectory=[u'/home/tuser1'],
krbprincipalname=[u'tuser1@' + api.env.realm],
loginshell=[u'/bin/sh'],
objectclass=objectclasses.user,
sn=[u'User1'],
uid=[user1],
gidnumber=[fuzzy_digits],
ipauniqueid=[fuzzy_uuid],
dn=u'uid=tuser1,cn=users,cn=accounts,' + api.env.basedn,
),
),
),
dict(
desc='Try to create duplicate %r' % user1,
command=( command=(
'user_add', [], dict(givenname=u'Test', sn=u'User1') 'user_add', [], dict(givenname=u'Test', sn=u'User1')
), ),
@ -92,68 +97,70 @@ class test_user(Declarative):
dict( dict(
desc='Retrieve the user', desc='Retrieve %r' % user1,
command=( command=(
'user_show', [u'tuser1'], {} 'user_show', [user1], {}
), ),
expected=dict( expected=dict(
result=dict( result=dict(
dn=u'uid=tuser1,cn=users,cn=accounts,dc=example,dc=com', dn=u'uid=tuser1,cn=users,cn=accounts,dc=example,dc=com',
givenname=(u'Test',), givenname=[u'Test'],
homedirectory=(u'/home/tuser1',), homedirectory=[u'/home/tuser1'],
loginshell=(u'/bin/sh',), loginshell=[u'/bin/sh'],
sn=(u'User1',), sn=[u'User1'],
uid=(u'tuser1',), uid=[user1],
), ),
value=u'tuser1', value=user1,
summary=None, summary=None,
), ),
), ),
dict( dict(
desc='Search for this user with all=True', desc='Search for %r with all=True' % user1,
command=( command=(
'user_find', [u'tuser1'], {'all': True} 'user_find', [user1], {'all': True}
), ),
expected=dict( expected=dict(
result=( result=[
{ {
'cn': (u'Test User1',), 'cn': [u'Test User1'],
'gecos': (u'tuser1',), 'gecos': [user1],
'givenname': (u'Test',), 'givenname': [u'Test'],
'homedirectory': (u'/home/tuser1',), 'homedirectory': [u'/home/tuser1'],
'krbprincipalname': (u'tuser1@' + api.env.realm,), 'krbprincipalname': [u'tuser1@' + api.env.realm],
'loginshell': (u'/bin/sh',), 'loginshell': [u'/bin/sh'],
'memberof group': (u'ipausers',), 'memberof group': [u'ipausers'],
'objectclass': user_objectclass, 'objectclass': objectclasses.user,
'sn': (u'User1',), 'sn': [u'User1'],
'uid': (u'tuser1',), 'uid': [user1],
'uidnumber': [fuzzy_digits],
'gidnumber': [fuzzy_digits],
'ipauniqueid': [fuzzy_uuid],
}, },
), ],
summary=u'1 user matched', summary=u'1 user matched',
count=1, count=1,
truncated=False, truncated=False,
), ),
ignore_values=['uidnumber', 'gidnumber', 'ipauniqueid'],
), ),
dict( dict(
desc='Search for this user with minimal attributes', desc='Search for %r with minimal attributes' % user1,
command=( command=(
'user_find', [u'tuser1'], {} 'user_find', [user1], {}
), ),
expected=dict( expected=dict(
result=( result=[
dict( dict(
givenname=(u'Test',), givenname=[u'Test'],
homedirectory=(u'/home/tuser1',), homedirectory=[u'/home/tuser1'],
loginshell=(u'/bin/sh',), loginshell=[u'/bin/sh'],
sn=(u'User1',), sn=[u'User1'],
uid=(u'tuser1',), uid=[user1],
), ),
), ],
summary=u'1 user matched', summary=u'1 user matched',
count=1, count=1,
truncated=False, truncated=False,
@ -167,21 +174,21 @@ class test_user(Declarative):
'user_find', [], {} 'user_find', [], {}
), ),
expected=dict( expected=dict(
result=( result=[
dict( dict(
homedirectory=(u'/home/admin',), homedirectory=[u'/home/admin'],
loginshell=(u'/bin/bash',), loginshell=[u'/bin/bash'],
sn=(u'Administrator',), sn=[u'Administrator'],
uid=(u'admin',), uid=[u'admin'],
), ),
dict( dict(
givenname=(u'Test',), givenname=[u'Test'],
homedirectory=(u'/home/tuser1',), homedirectory=[u'/home/tuser1'],
loginshell=(u'/bin/sh',), loginshell=[u'/bin/sh'],
sn=(u'User1',), sn=[u'User1'],
uid=(u'tuser1',), uid=[user1],
), ),
), ],
summary=u'2 users matched', summary=u'2 users matched',
count=2, count=2,
truncated=False, truncated=False,
@ -190,95 +197,95 @@ class test_user(Declarative):
dict( dict(
desc='Lock user', desc='Lock %r' % user1,
command=( command=(
'user_lock', [u'tuser1'], {} 'user_lock', [user1], {}
), ),
expected=dict( expected=dict(
result=True, result=True,
value=u'tuser1', value=user1,
summary=u'Locked user "tuser1"', summary=u'Locked user "tuser1"',
), ),
), ),
dict( dict(
desc='Unlock user', desc='Unlock %r' % user1,
command=( command=(
'user_unlock', [u'tuser1'], {} 'user_unlock', [user1], {}
), ),
expected=dict( expected=dict(
result=True, result=True,
value=u'tuser1', value=user1,
summary=u'Unlocked user "tuser1"', summary=u'Unlocked user "tuser1"',
), ),
), ),
dict( dict(
desc='Update user', desc='Update %r' % user1,
command=( command=(
'user_mod', [u'tuser1'], dict(givenname=u'Finkle') 'user_mod', [user1], dict(givenname=u'Finkle')
), ),
expected=dict( expected=dict(
result=dict( result=dict(
givenname=(u'Finkle',), givenname=[u'Finkle'],
), ),
summary=u'Modified user "tuser1"', summary=u'Modified user "tuser1"',
value=u'tuser1', value=user1,
), ),
), ),
dict( dict(
desc='Retrieve user to verify update', desc='Retrieve %r to verify update' % user1,
command=( command=('user_show', [user1], {}),
'user_show', [u'tuser1'], {}
),
expected=dict( expected=dict(
result=dict( result=dict(
dn=u'uid=tuser1,cn=users,cn=accounts,dc=example,dc=com', dn=u'uid=tuser1,cn=users,cn=accounts,dc=example,dc=com',
givenname=(u'Finkle',), givenname=[u'Finkle'],
homedirectory=(u'/home/tuser1',), homedirectory=[u'/home/tuser1'],
loginshell=(u'/bin/sh',), loginshell=[u'/bin/sh'],
sn=(u'User1',), sn=[u'User1'],
uid=(u'tuser1',), uid=[user1],
), ),
summary=None, summary=None,
value=u'tuser1', value=user1,
), ),
), ),
dict( dict(
desc='Delete user', desc='Delete %r' % user1,
command=( command=('user_del', [user1], {}),
'user_del', [u'tuser1'], {}
),
expected=dict( expected=dict(
result=True, result=True,
summary=u'Deleted user "tuser1"', summary=u'Deleted user "tuser1"',
value=u'tuser1', value=user1,
), ),
), ),
dict( dict(
desc='Do double delete', desc='Try to delete non-existent %r' % user1,
command=( command=('user_del', [user1], {}),
'user_del', [u'tuser1'], {}
),
expected=errors.NotFound(reason='no such entry'), expected=errors.NotFound(reason='no such entry'),
), ),
dict( dict(
desc='Verify user is gone', desc='Try to retrieve non-existent %r' % user1,
command=( command=('user_show', [user1], {}),
'user_show', [u'tuser1'], {}
),
expected=errors.NotFound(reason='no such entry'), expected=errors.NotFound(reason='no such entry'),
), ),
dict(
desc='Try to update non-existent %r' % user1,
command=('user_mod', [user1], dict(givenname=u'Foo')),
expected=errors.NotFound(reason='no such entry'),
),
] ]

View File

@ -24,11 +24,22 @@ Base class for all XML-RPC tests
import sys import sys
import socket import socket
import nose import nose
from tests.util import assert_deepequal from tests.util import assert_deepequal, Fuzzy
from ipalib import api, request from ipalib import api, request
from ipalib import errors from ipalib import errors
# Matches a gidnumber like '1391016742'
# FIXME: Does it make more sense to return gidnumber, uidnumber, etc. as `int`
# or `long`? If not, we still need to return them as `unicode` instead of `str`.
fuzzy_digits = Fuzzy('^\d+$', type=str)
# Matches an ipauniqueid like u'784d85fd-eae7-11de-9d01-54520012478b'
fuzzy_uuid = Fuzzy(
'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'
)
try: try:
if not api.Backend.xmlclient.isconnected(): if not api.Backend.xmlclient.isconnected():
api.Backend.xmlclient.connect() api.Backend.xmlclient.connect()
@ -146,10 +157,10 @@ class Declarative(XMLRPC_test):
tests = tuple() tests = tuple()
def cleanup_generate(self, stage): def cleanup_generate(self, stage):
for command in self.cleanup_commands: for (i, command) in enumerate(self.cleanup_commands):
func = lambda: self.cleanup(command) func = lambda: self.cleanup(command)
func.description = '%s %s-cleanup: %r' % ( func.description = '%s %s-cleanup[%d]: %r' % (
self.__class__.__name__, stage, command self.__class__.__name__, stage, i, command
) )
yield (func,) yield (func,)
@ -194,11 +205,10 @@ class Declarative(XMLRPC_test):
if cmd not in api.Command: if cmd not in api.Command:
raise nose.SkipTest('%r not in api.Command' % cmd) raise nose.SkipTest('%r not in api.Command' % cmd)
expected = test['expected'] expected = test['expected']
ignore_values = test.get('ignore_values')
if isinstance(expected, errors.PublicError): if isinstance(expected, errors.PublicError):
self.check_exception(nice, cmd, args, options, expected) self.check_exception(nice, cmd, args, options, expected)
else: else:
self.check_output(nice, cmd, args, options, expected, ignore_values) self.check_output(nice, cmd, args, options, expected)
def check_exception(self, nice, cmd, args, options, expected): def check_exception(self, nice, cmd, args, options, expected):
klass = expected.__class__ klass = expected.__class__
@ -224,28 +234,6 @@ class Declarative(XMLRPC_test):
# KWARGS % (cmd, name, args, options, expected.kw, e.kw) # KWARGS % (cmd, name, args, options, expected.kw, e.kw)
# ) # )
def check_output(self, nice, cmd, args, options, expected, ignore_values): def check_output(self, nice, cmd, args, options, expected):
got = api.Command[cmd](*args, **options) got = api.Command[cmd](*args, **options)
result = got['result']
if ignore_values:
if isinstance(result, dict):
self.clean_entry(
nice, cmd, args, options, result, ignore_values
)
elif isinstance(result, (list, tuple)):
for entry in result:
self.clean_entry(
nice, cmd, args, options, entry, ignore_values
)
assert_deepequal(expected, got, nice) assert_deepequal(expected, got, nice)
def clean_entry(self, nice, cmd, args, options, entry, ignore_values):
"""
Remove attributes like 'ipauniqueid' whose value is unpredictable.
"""
for key in ignore_values:
if key not in entry:
raise AssertionError(
IGNORE % (cmd, key, args, options, entry)
)
entry.pop(key)

View File

@ -26,6 +26,7 @@ import os
from os import path from os import path
import tempfile import tempfile
import shutil import shutil
import re
import ipalib import ipalib
from ipalib.plugable import Plugin from ipalib.plugable import Plugin
from ipalib.request import context from ipalib.request import context
@ -108,6 +109,58 @@ def assert_equal(val1, val2):
assert val1 == val2, '%r != %r' % (val1, val2) assert val1 == val2, '%r != %r' % (val1, val2)
class Fuzzy(object):
"""
Perform a fuzzy (non-strict) equality test.
`Fuzzy` instances will likely be used when comparing nesting data-structures
using `assert_deepequal()`.
"""
def __init__(self, regex=None, type=None, test=None):
"""
Initialize.
:param regex: A regular expression pattern to match, e.g.
``u'^\d+foo'``
:param type: A type or tuple of types to test using ``isinstance()``,
e.g. ``(int, float)``
:param test: A callable used to perform equality test, e.g.
``lambda other: other >= 18``
"""
assert regex is None or isinstance(regex, basestring)
assert test is None or callable(test)
if regex is None:
self.re = None
else:
self.re = re.compile(regex)
if type is None:
type = unicode
assert type in (unicode, str)
self.regex = regex
self.type = type
self.test = test
def __repr__(self):
return '%s(regex=%r, type=%r, test=%r)' % (
self.__class__.__name__, self.regex, self.type, self.test
)
def __eq__(self, other):
if not (self.type is None or isinstance(other, self.type)):
return False
if not (self.re is None or self.re.search(other)):
return False
if not (self.test is None or self.test(other)):
return False
return True
def __ne__(self, other):
return not self.__eq__(other)
VALUE = """assert_deepequal: expected != got. VALUE = """assert_deepequal: expected != got.
%s %s
expected = %r expected = %r
@ -160,7 +213,11 @@ def assert_deepequal(expected, got, src='', stack=tuple()):
got = 'nurse' got = 'nurse'
path = (1, 'naughty') path = (1, 'naughty')
""" """
if type(expected) is not type(got): if isinstance(expected, tuple):
expected = list(expected)
if isinstance(got, tuple):
got = list(got)
if not (isinstance(expected, Fuzzy) or type(expected) is type(got)):
raise AssertionError( raise AssertionError(
TYPE % (src, type(expected), type(got), expected, got, stack) TYPE % (src, type(expected), type(got), expected, got, stack)
) )
@ -184,7 +241,7 @@ def assert_deepequal(expected, got, src='', stack=tuple()):
e_sub = expected[key] e_sub = expected[key]
g_sub = got[key] g_sub = got[key]
assert_deepequal(e_sub, g_sub, src, stack + (key,)) assert_deepequal(e_sub, g_sub, src, stack + (key,))
if expected != got: elif expected != got:
raise AssertionError( raise AssertionError(
VALUE % (src, expected, got, stack) VALUE % (src, expected, got, stack)
) )