diff --git a/congress/datalog/compile.py b/congress/datalog/compile.py index f42eb3194..6ed6923fa 100644 --- a/congress/datalog/compile.py +++ b/congress/datalog/compile.py @@ -1364,7 +1364,7 @@ class RuleDependencyGraph(utility.BagGraph): # TODO(thinrichs): should be able to have global_tablename # return a Tablename object and therefore build a graph # of Tablename objects instead of strings. - if is_atom(formula): + if is_atom_like(formula): if include_atoms: table = formula.table.global_tablename(theory) nodes.add(table) @@ -1804,6 +1804,22 @@ def is_regular_rule(x): return (is_rule(x) and len(x.heads) == 1) +def is_atom_rule(x): + return is_regular_rule(x) and len(x.body) == 0 and is_literal(x.heads[0]) + + +def is_literal_rule(x): + return is_regular_rule(x) and len(x.body) == 0 and is_literal(x.heads[0]) + + +def is_atom_like(x): + return is_atom(x) or is_atom_rule(x) + + +def is_literal_like(x): + return is_literal(x) or is_literal_rule(x) + + def is_multi_rule(x): """Returns True if X is a rule with multiple heads.""" return (is_rule(x) and len(x.heads) != 1) diff --git a/congress/tests/policy_engines/test_agnostic.py b/congress/tests/policy_engines/test_agnostic.py index 198d9b78e..4d94d7237 100644 --- a/congress/tests/policy_engines/test_agnostic.py +++ b/congress/tests/policy_engines/test_agnostic.py @@ -919,6 +919,26 @@ class TestMultipolicyRules(base.TestCase): self.assertEqual(len(errors), 1) self.assertIn("Rules are recursive", str(errors[0])) + def test_dependency_graph_policy_deletion(self): + run = agnostic.Runtime() + g = run.global_dependency_graph + run.create_policy('test') + rule = 'execute[nova:flavors.delete(id)] :- nova:flavors(id)' + permitted, changes = run.insert(rule, target='test') + self.assertTrue(permitted) + run.create_policy('nova') + run.insert('flavors(1)', target="nova") + run.insert('flavors(2)', target="nova") + run.insert('flavors(3)', target="nova") + run.insert('flavors(4)', target="nova") + + self.assertEqual(g.dependencies('test:nova:flavors.delete'), + set(['nova:flavors', 'test:nova:flavors.delete'])) + run.delete_policy('nova') + self.assertTrue(g.node_in('nova:flavors')) + self.assertEqual(g.dependencies('test:nova:flavors.delete'), + set(['nova:flavors', 'test:nova:flavors.delete'])) + def test_dependency_graph(self): """Test that dependency graph gets updated correctly.""" run = agnostic.Runtime()