diff options
-rw-r--r-- | ipalib/frontend.py | 23 | ||||
-rw-r--r-- | tests/test_ipalib/test_frontend.py | 20 |
2 files changed, 31 insertions, 12 deletions
diff --git a/ipalib/frontend.py b/ipalib/frontend.py index c28fa54ae..fadcb8632 100644 --- a/ipalib/frontend.py +++ b/ipalib/frontend.py @@ -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)): diff --git a/tests/test_ipalib/test_frontend.py b/tests/test_ipalib/test_frontend.py index 5f7ce65fb..528609d9e 100644 --- a/tests/test_ipalib/test_frontend.py +++ b/tests/test_ipalib/test_frontend.py @@ -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 |