def test_dependencies(self): g = compile.RuleDependencyGraph() g.formula_insert(compile.parse1('p(x) :- q(x), r(x)')) g.formula_insert(compile.parse1('q(x) :- t(x), not s(x)')) self.assertEqual(g.dependencies('p'), set(['p', 'q', 'r', 't', 's'])) self.assertEqual(g.dependencies('q'), set(['q', 't', 's'])) self.assertEqual(g.dependencies('r'), set(['r'])) self.assertEqual(g.dependencies('t'), set(['t'])) self.assertEqual(g.dependencies('s'), set(['s'])) # cyclic case g = compile.RuleDependencyGraph() g.formula_insert(compile.parse1('p(x) :- q(x), r(x)')) g.formula_insert(compile.parse1('q(x) :- t(x), not s(x)')) g.formula_insert(compile.parse1('t(x) :- t(x), p(x), q(x)')) self.assertEqual(g.dependencies('p'), set(['p', 'q', 'r', 't', 's'])) self.assertEqual(g.dependencies('q'), set(['p', 'q', 'r', 't', 's'])) self.assertEqual(g.dependencies('r'), set(['r'])) self.assertEqual(g.dependencies('t'), set(['p', 'q', 'r', 't', 's'])) self.assertEqual(g.dependencies('s'), set(['s'])) g = compile.RuleDependencyGraph(head_to_body=False) g.formula_insert(compile.parse1('p(x) :- q(x), r(x)')) g.formula_insert(compile.parse1('q(x) :- t(x), not s(x)')) self.assertEqual(g.dependencies('p'), set(['p'])) self.assertEqual(g.dependencies('q'), set(['q', 'p'])) self.assertEqual(g.dependencies('r'), set(['r', 'p'])) self.assertEqual(g.dependencies('t'), set(['t', 'q', 'p'])) self.assertEqual(g.dependencies('s'), set(['s', 'q', 'p']))
def test_modals(self): g = compile.RuleDependencyGraph() g.formula_insert(compile.parse1('p(x) :- q(x)')) g.formula_insert(compile.parse1('q(x) :- r(x)')) g.formula_insert(compile.parse1('execute[p(x)] :- q(x)')) chgs = g.formula_insert(compile.parse1('execute[r(x)] :- q(x)')) g.formula_insert(compile.parse1('insert[s(x)] :- q(x)')) self.assertEqual(set(g.tables_with_modal('execute')), set(['p', 'r'])) g.undo_changes(chgs) self.assertEqual(set(g.tables_with_modal('execute')), set(['p'])) chgs = g.formula_delete(compile.parse1('execute[p(x)] :- q(x)')) self.assertEqual(set(g.tables_with_modal('execute')), set()) g.undo_changes(chgs) self.assertEqual(set(g.tables_with_modal('execute')), set(['p']))
def test_basic_dependency(self): g = compile.RuleDependencyGraph() reg = agnostic.TriggerRegistry(g) g.formula_insert(compile.parse1('p(x) :- q(x)'), 'alice') # register p p_trigger = reg.register_table('p', 'alice', self.f) self.assertEqual(reg.relevant_triggers(['alice:q']), set([p_trigger])) self.assertEqual(reg.relevant_triggers(['alice:p']), set([p_trigger])) # register q q_trigger = reg.register_table('q', 'alice', self.f) self.assertEqual(reg.relevant_triggers(['alice:q']), set([p_trigger, q_trigger])) self.assertEqual(reg.relevant_triggers(['alice:p']), set([p_trigger]))
def test_unregister(self): g = compile.RuleDependencyGraph() reg = agnostic.TriggerRegistry(g) p_trigger = reg.register_table('p', 'alice', self.f) q_trigger = reg.register_table('q', 'alice', self.f) self.assertEqual(reg.relevant_triggers(['alice:p']), set([p_trigger])) self.assertEqual(reg.relevant_triggers(['alice:q']), set([q_trigger])) # unregister p reg.unregister(p_trigger) self.assertEqual(reg.relevant_triggers(['alice:p']), set()) self.assertEqual(reg.relevant_triggers(['alice:q']), set([q_trigger])) # unregister q reg.unregister(q_trigger) self.assertEqual(reg.relevant_triggers(['alice:p']), set()) self.assertEqual(reg.relevant_triggers(['alice:q']), set()) # unregister nonexistent trigger self.assertRaises(KeyError, reg.unregister, p_trigger) self.assertEqual(reg.relevant_triggers(['alice:p']), set()) self.assertEqual(reg.relevant_triggers(['alice:q']), set())
def test_register(self): g = compile.RuleDependencyGraph() reg = agnostic.TriggerRegistry(g) # register p_trigger = reg.register_table('p', 'alice', self.f) triggers = reg.relevant_triggers(['alice:p']) self.assertEqual(triggers, set([p_trigger])) # register 2nd table q_trigger = reg.register_table('q', 'alice', self.f) p_triggers = reg.relevant_triggers(['alice:p']) self.assertEqual(p_triggers, set([p_trigger])) q_triggers = reg.relevant_triggers(['alice:q']) self.assertEqual(q_triggers, set([q_trigger])) # register again with table p p2_trigger = reg.register_table('p', 'alice', self.f) p_triggers = reg.relevant_triggers(['alice:p']) self.assertEqual(p_triggers, set([p_trigger, p2_trigger])) q_triggers = reg.relevant_triggers(['alice:q']) self.assertEqual(q_triggers, set([q_trigger]))
def test_nodes_edges(self): g = compile.RuleDependencyGraph() # first insertion g.formula_insert(compile.parse1('p(x), q(x) :- r(x), s(x)')) self.assertTrue(g.node_in('p')) self.assertTrue(g.node_in('q')) self.assertTrue(g.node_in('r')) self.assertTrue(g.node_in('s')) self.assertTrue(g.edge_in('p', 'r', False)) self.assertTrue(g.edge_in('p', 's', False)) self.assertTrue(g.edge_in('q', 'r', False)) self.assertTrue(g.edge_in('q', 's', False)) self.assertFalse(g.has_cycle()) # another insertion g.formula_insert(compile.parse1('r(x) :- t(x)')) self.assertTrue(g.node_in('p')) self.assertTrue(g.node_in('q')) self.assertTrue(g.node_in('r')) self.assertTrue(g.node_in('s')) self.assertTrue(g.edge_in('p', 'r', False)) self.assertTrue(g.edge_in('p', 's', False)) self.assertTrue(g.edge_in('q', 'r', False)) self.assertTrue(g.edge_in('q', 's', False)) self.assertTrue(g.node_in('t')) self.assertTrue(g.edge_in('r', 't', False)) self.assertFalse(g.has_cycle()) # 3rd insertion, creating a cycle g.formula_insert(compile.parse1('t(x) :- p(x)')) self.assertTrue(g.edge_in('t', 'p', False)) self.assertTrue(g.has_cycle()) # deletion g.formula_delete(compile.parse1('p(x), q(x) :- r(x), s(x)')) self.assertTrue(g.node_in('p')) self.assertTrue(g.node_in('r')) self.assertTrue(g.node_in('t')) self.assertTrue(g.edge_in('r', 't', False)) self.assertTrue(g.edge_in('t', 'p', False)) self.assertFalse(g.has_cycle()) # double-insertion g.formula_insert(compile.parse1('p(x) :- q(x), r(x)')) g.formula_insert(compile.parse1('p(1) :- r(1)')) self.assertTrue(g.has_cycle()) # deletion -- checking for bag semantics g.formula_delete(compile.parse1('p(1) :- r(1)')) self.assertTrue(g.has_cycle()) g.formula_delete(compile.parse1('p(x) :- q(x), r(x)')) self.assertFalse(g.has_cycle()) # update g.formula_update([ compile.Event(compile.parse1('a(x) :- b(x)')), compile.Event(compile.parse1('b(x) :- c(x)')), compile.Event(compile.parse1('c(x) :- a(x)')) ]) self.assertTrue(g.has_cycle()) g.formula_update( [compile.Event(compile.parse1('c(x) :- a(x)'), insert=False)]) self.assertFalse(g.has_cycle()) # cycle enumeration g = compile.RuleDependencyGraph() g.formula_insert(compile.parse1('p(x) :- q(x), r(x)')) g.formula_insert(compile.parse1('q(x) :- t(x), not s(x)')) g.formula_insert(compile.parse1('t(x) :- t(x), p(x), q(x)')) self.assertTrue(g.has_cycle()) self.assertEqual(len(g.cycles()), 3) expected_cycle_set = set([ utility.Cycle(['p', 'q', 't', 'p']), utility.Cycle(['q', 't', 'q']), utility.Cycle(['t', 't']) ]) actual_cycle_set = set([ utility.Cycle(g.cycles()[0]), utility.Cycle(g.cycles()[1]), utility.Cycle(g.cycles()[2]) ]) self.assertEqual(expected_cycle_set, actual_cycle_set)
def test_complex_dependency(self): g = compile.RuleDependencyGraph() reg = agnostic.TriggerRegistry(g) g.formula_insert(compile.parse1('p(x) :- q(x)'), 'alice') g.formula_insert(compile.parse1('q(x) :- r(x), s(x)'), 'alice') g.formula_insert(compile.parse1('r(x) :- t(x, y), u(y)'), 'alice') g.formula_insert(compile.parse1('separate(x) :- separate2(x)'), 'alice') g.formula_insert(compile.parse1('notrig(x) :- notrig2(x)'), 'alice') p_trigger = reg.register_table('p', 'alice', self.f) sep_trigger = reg.register_table('separate', 'alice', self.f) # individual tables self.assertEqual(reg.relevant_triggers(['alice:p']), set([p_trigger])) self.assertEqual(reg.relevant_triggers(['alice:q']), set([p_trigger])) self.assertEqual(reg.relevant_triggers(['alice:r']), set([p_trigger])) self.assertEqual(reg.relevant_triggers(['alice:s']), set([p_trigger])) self.assertEqual(reg.relevant_triggers(['alice:t']), set([p_trigger])) self.assertEqual(reg.relevant_triggers(['alice:u']), set([p_trigger])) self.assertEqual(reg.relevant_triggers(['alice:notrig']), set()) self.assertEqual(reg.relevant_triggers(['alice:notrig2']), set([])) self.assertEqual(reg.relevant_triggers(['alice:separate']), set([sep_trigger])) self.assertEqual(reg.relevant_triggers(['alice:separate2']), set([sep_trigger])) # groups of tables self.assertEqual(reg.relevant_triggers(['alice:p', 'alice:q']), set([p_trigger])) self.assertEqual(reg.relevant_triggers(['alice:separate', 'alice:p']), set([p_trigger, sep_trigger])) self.assertEqual(reg.relevant_triggers(['alice:notrig', 'alice:p']), set([p_trigger])) # events: data event = compile.Event(compile.parse1('q(1)'), target='alice') self.assertEqual(reg.relevant_triggers([event]), set([p_trigger])) event = compile.Event(compile.parse1('u(1)'), target='alice') self.assertEqual(reg.relevant_triggers([event]), set([p_trigger])) event = compile.Event(compile.parse1('separate2(1)'), target='alice') self.assertEqual(reg.relevant_triggers([event]), set([sep_trigger])) event = compile.Event(compile.parse1('notrig2(1)'), target='alice') self.assertEqual(reg.relevant_triggers([event]), set([])) # events: rules event = compile.Event(compile.parse1('separate(x) :- q(x)'), target='alice') self.assertEqual(reg.relevant_triggers([event]), set([sep_trigger])) event = compile.Event(compile.parse1('notrig(x) :- q(x)'), target='alice') self.assertEqual(reg.relevant_triggers([event]), set([])) event = compile.Event(compile.parse1('r(x) :- q(x)'), target='alice') self.assertEqual(reg.relevant_triggers([event]), set([p_trigger])) # events: multiple rules and data event1 = compile.Event(compile.parse1('r(x) :- q(x)'), target='alice') event2 = compile.Event(compile.parse1('separate2(1)'), target='alice') self.assertEqual(reg.relevant_triggers([event1, event2]), set([p_trigger, sep_trigger])) event1 = compile.Event(compile.parse1('r(x) :- q(x)'), target='alice') event2 = compile.Event(compile.parse1('notrigger2(1)'), target='alice') self.assertEqual(reg.relevant_triggers([event1, event2]), set([p_trigger]))