summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Laski <andrew@lascii.com>2016-05-25 17:01:37 -0400
committerAndrew Laski <andrew@lascii.com>2016-06-06 10:11:50 -0400
commitea29939194663d6d1028a242cc880002bdfc8ace (patch)
tree4b6023ea27b79976bd23ada64dbfd20c378ca17a
parentf5988a259694adc225ead4a22ead057ef2fa3564 (diff)
downloadoslo-policy-ea29939194663d6d1028a242cc880002bdfc8ace.tar.gz
Add equality operator to policy.RuleDefault
There are occasions when comparing two RuleDefault objects is needed. Rather than embedding the logic at the comparison site it's preferable to let the object know how to compare itself to another. Change-Id: I2eae5665fdecd6638e84f577b506314f7bc03fd3
-rw-r--r--oslo_policy/policy.py20
-rw-r--r--oslo_policy/tests/test_policy.py54
2 files changed, 74 insertions, 0 deletions
diff --git a/oslo_policy/policy.py b/oslo_policy/policy.py
index 7271b53..cd4c201 100644
--- a/oslo_policy/policy.py
+++ b/oslo_policy/policy.py
@@ -706,3 +706,23 @@ class RuleDefault(object):
def __str__(self):
return '"%(name)s": "%(check_str)s"' % {'name': self.name,
'check_str': self.check_str}
+
+ def __eq__(self, other):
+ """Equality operator.
+
+ All check objects have a stable string representation. It is used for
+ comparison rather than check_str because multiple check_str's may parse
+ to the same check object. For instance '' and '@' are equivalent and
+ the parsed rule string representation for both is '@'.
+
+ The description does not play a role in the meaning of the check so it
+ is not considered for equality.
+ """
+ # Name should match, check should match, and class should be equivalent
+ # or one should be a subclass of the other.
+ if (self.name == other.name and
+ str(self.check) == str(other.check) and
+ (isinstance(self, other.__class__) or
+ isinstance(other, self.__class__))):
+ return True
+ return False
diff --git a/oslo_policy/tests/test_policy.py b/oslo_policy/tests/test_policy.py
index e5c9887..51565af 100644
--- a/oslo_policy/tests/test_policy.py
+++ b/oslo_policy/tests/test_policy.py
@@ -719,3 +719,57 @@ class RuleDefaultTestCase(base.PolicyBaseTestCase):
def test_str(self):
opt = policy.RuleDefault(name='foo', check_str='rule:foo')
self.assertEqual('"foo": "rule:foo"', str(opt))
+
+ def test_equality_obvious(self):
+ opt1 = policy.RuleDefault(name='foo', check_str='rule:foo',
+ description='foo')
+ opt2 = policy.RuleDefault(name='foo', check_str='rule:foo',
+ description='bar')
+ self.assertEqual(opt1, opt2)
+
+ def test_equality_less_obvious(self):
+ opt1 = policy.RuleDefault(name='foo', check_str='',
+ description='foo')
+ opt2 = policy.RuleDefault(name='foo', check_str='@',
+ description='bar')
+ self.assertEqual(opt1, opt2)
+
+ def test_not_equal_check(self):
+ opt1 = policy.RuleDefault(name='foo', check_str='rule:foo',
+ description='foo')
+ opt2 = policy.RuleDefault(name='foo', check_str='rule:bar',
+ description='bar')
+ self.assertNotEqual(opt1, opt2)
+
+ def test_not_equal_name(self):
+ opt1 = policy.RuleDefault(name='foo', check_str='rule:foo',
+ description='foo')
+ opt2 = policy.RuleDefault(name='bar', check_str='rule:foo',
+ description='bar')
+ self.assertNotEqual(opt1, opt2)
+
+ def test_not_equal_class(self):
+ class NotRuleDefault(object):
+ def __init__(self, name, check_str):
+ self.name = name
+ self.check = _parser.parse_rule(check_str)
+
+ opt1 = policy.RuleDefault(name='foo', check_str='rule:foo')
+ opt2 = NotRuleDefault(name='foo', check_str='rule:foo')
+ self.assertNotEqual(opt1, opt2)
+
+ def test_equal_subclass(self):
+ class RuleDefaultSub(policy.RuleDefault):
+ pass
+
+ opt1 = policy.RuleDefault(name='foo', check_str='rule:foo')
+ opt2 = RuleDefaultSub(name='foo', check_str='rule:foo')
+ self.assertEqual(opt1, opt2)
+
+ def test_not_equal_subclass(self):
+ class RuleDefaultSub(policy.RuleDefault):
+ pass
+
+ opt1 = policy.RuleDefault(name='foo', check_str='rule:foo')
+ opt2 = RuleDefaultSub(name='bar', check_str='rule:foo')
+ self.assertNotEqual(opt1, opt2)