Improve output validation

We only checked the length of Command output dictionaries. A misspelled
key in would not be caught.

Fix the problem by checking if the sets of keys are equal.

Add a test. Split the test methods into more manageable pieces.

https://fedorahosted.org/freeipa/ticket/2860
This commit is contained in:
Petr Viktorin
2012-06-15 09:08:55 -04:00
committed by Rob Crittenden
parent ec5115a155
commit 3021b3e9d5
2 changed files with 31 additions and 12 deletions

View File

@@ -913,16 +913,19 @@ class Command(HasParam):
raise TypeError('%s: need a %r; got a %r: %r' % (
nice, dict, type(output), output)
)
if len(output) < len(self.output):
missing = sorted(set(self.output).difference(output))
raise ValueError('%s: missing keys %r in %r' % (
nice, missing, output)
)
if len(output) > len(self.output):
extra = sorted(set(output).difference(self.output))
raise ValueError('%s: unexpected keys %r in %r' % (
nice, extra, output)
)
expected_set = set(self.output)
actual_set = set(output)
if expected_set != actual_set:
missing = expected_set - actual_set
if missing:
raise ValueError('%s: missing keys %r in %r' % (
nice, sorted(missing), output)
)
extra = actual_set - expected_set
if extra:
raise ValueError('%s: unexpected keys %r in %r' % (
nice, sorted(extra), output)
)
for o in self.output():
value = output[o.name]
if not (o.type is None or isinstance(value, o.type)):

View File

@@ -615,7 +615,7 @@ class test_Command(ClassChecker):
assert o.run.im_func is self.cls.run.im_func
assert ('forward', args, kw) == o.run(*args, **kw)
def test_validate_output(self):
def test_validate_output_basic(self):
"""
Test the `ipalib.frontend.Command.validate_output` method.
"""
@@ -646,7 +646,18 @@ class test_Command(ClassChecker):
'Example', ['azz', 'fee'], wrong
)
# Test with per item type validation:
# Test with different keys:
wrong = dict(baz=1, xyzzy=2, quux=3)
e = raises(ValueError, inst.validate_output, wrong)
assert str(e) == '%s.validate_output(): missing keys %r in %r' % (
'Example', ['bar', 'foo'], wrong
), str(e)
def test_validate_output_per_type(self):
"""
Test `ipalib.frontend.Command.validate_output` per-type validation.
"""
class Complex(self.cls):
has_output = (
output.Output('foo', int),
@@ -667,6 +678,11 @@ class test_Command(ClassChecker):
'Complex.validate_output()', 'bar', list, int, 17
)
def test_validate_output_nested(self):
"""
Test `ipalib.frontend.Command.validate_output` nested validation.
"""
class Subclass(output.ListOfEntries):
pass