Ejemplo n.º 1
0
    def test_event_facts(self):
        # insert
        event = compile.parse('insert[p(1) :- true]')
        self.assertEqual(len(event), 1)
        event = event[0]
        fact = compile.parse1('p(1) :- true')
        self.assertEqual(event.formula, fact)
        self.assertEqual(event.insert, True)
        self.assertIsNone(event.target)

        # delete
        event = compile.parse('delete[p(1) :- true]')
        self.assertEqual(len(event), 1)
        event = event[0]
        fact = compile.parse1('p(1) :- true')
        self.assertEqual(event.formula, fact)
        self.assertEqual(event.insert, False)
        self.assertIsNone(event.target)

        # insert with policy
        event = compile.parse('insert[p(1) :- true; "policy"]')
        self.assertEqual(len(event), 1)
        event = event[0]
        fact = compile.parse1('p(1) :- true')
        self.assertEqual(event.formula, fact)
        self.assertEqual(event.insert, True)
        self.assertEqual(event.target, "policy")
Ejemplo n.º 2
0
 def check(self, atom1, atom2):
     atom1 = compile.parse1(atom1)
     atom2 = compile.parse1(atom2)
     unifier = unify.BiUnifier()
     changes = unify.match_atoms(atom1, unifier, atom2)
     self.assertIsNotNone(changes)
     self.assertEqual(atom1.plug(unifier), atom2)
Ejemplo n.º 3
0
    def test_event_facts(self):
        # insert
        event = compile.parse('insert[p(1) :- true]')
        self.assertEqual(len(event), 1)
        event = event[0]
        fact = compile.parse1('p(1) :- true')
        self.assertEqual(event.formula, fact)
        self.assertEqual(event.insert, True)
        self.assertIsNone(event.target)

        # delete
        event = compile.parse('delete[p(1) :- true]')
        self.assertEqual(len(event), 1)
        event = event[0]
        fact = compile.parse1('p(1) :- true')
        self.assertEqual(event.formula, fact)
        self.assertEqual(event.insert, False)
        self.assertIsNone(event.target)

        # insert with policy
        event = compile.parse('insert[p(1) :- true; "policy"]')
        self.assertEqual(len(event), 1)
        event = event[0]
        fact = compile.parse1('p(1) :- true')
        self.assertEqual(event.formula, fact)
        self.assertEqual(event.insert, True)
        self.assertEqual(event.target, "policy")
Ejemplo n.º 4
0
 def check(self, atom1, atom2):
     atom1 = compile.parse1(atom1)
     atom2 = compile.parse1(atom2)
     unifier = unify.BiUnifier()
     changes = unify.match_atoms(atom1, unifier, atom2)
     self.assertIsNotNone(changes)
     self.assertEqual(atom1.plug(unifier), atom2)
Ejemplo n.º 5
0
 def check(self, input_string, correct_string, msg):
     rule = compile.parse1(input_string)
     actual = compile.reorder_for_safety(rule)
     correct = compile.parse1(correct_string)
     if correct != actual:
         emsg = "Correct: " + str(correct)
         emsg += "; Actual: " + str(actual)
         self.fail(msg + " :: " + emsg)
Ejemplo n.º 6
0
 def test_rule_hash(self):
     """Test whether rules are properly hashed."""
     s = set()
     p = compile.parse1('p(x) :- q(x), s(x,y)')
     s.add(p)
     q = compile.parse1('p(x) :- q(x), s(x,y)')
     s.discard(q)
     self.assertEqual(s, set())
Ejemplo n.º 7
0
 def test_rule_hash(self):
     """Test whether rules are properly hashed."""
     s = set()
     p = compile.parse1('p(x) :- q(x), s(x,y)')
     s.add(p)
     q = compile.parse1('p(x) :- q(x), s(x,y)')
     s.discard(q)
     self.assertEqual(s, set())
Ejemplo n.º 8
0
 def test_hash(self):
     x = set()
     x.add(compile.parse1('p(x, y) :- nova:q(x, id=y)'))
     x.add(compile.parse1('p(x, y) :- nova:q(x, id=y)'))
     self.assertEqual(len(x), 1)
     self.assertIn(compile.parse1('p(x, y) :- nova:q(x, id=y)'), x)
     x.discard(compile.parse1('p(x, y) :- nova:q(x, id=y)'))
     self.assertEqual(len(x), 0)
Ejemplo n.º 9
0
 def check(self, input_string, correct_string, msg):
     rule = compile.parse1(input_string)
     actual = compile.reorder_for_safety(rule)
     correct = compile.parse1(correct_string)
     if correct != actual:
         emsg = "Correct: " + str(correct)
         emsg += "; Actual: " + str(actual)
         self.fail(msg + " :: " + emsg)
Ejemplo n.º 10
0
 def test_hash(self):
     x = set()
     x.add(compile.parse1('p(x, y) :- nova:q(x, id=y)'))
     x.add(compile.parse1('p(x, y) :- nova:q(x, id=y)'))
     self.assertEqual(len(x), 1)
     self.assertIn(compile.parse1('p(x, y) :- nova:q(x, id=y)'), x)
     x.discard(compile.parse1('p(x, y) :- nova:q(x, id=y)'))
     self.assertEqual(len(x), 0)
Ejemplo n.º 11
0
    def test_no_split_parsing(self):
        th = nonrecursive.NonrecursiveRuleTheory()
        th.insert(compile.parse1("nova:v(x, y) :- u(x, y)", use_modules=False))

        self.assertEqual(th.arity("nova:v"), 2)
        self.assertIsNone(th.arity("nova:v", modal="insert"))
        th.insert(compile.parse1("insert[neutron:v(x, y, z)] :- u(x, y)", use_modules=False))
        self.assertEqual(th.arity("nova:v"), 2)
        self.assertEqual(th.arity("neutron:v", modal="insert"), 3)
Ejemplo n.º 12
0
    def test_module_schemas(self):
        """Test that rules are properly checked against module schemas."""

        run = agnostic.Runtime()
        run.create_policy('mod1')
        run.create_policy('mod2')
        run.set_schema('mod1', compile.Schema({'p': (1, 2, 3), 'q': (1,)}),
                       complete=True)
        run.set_schema('mod2', compile.Schema({'p': (1,), 'q': (1, 2)}),
                       complete=True)

        def check_err(code_string, theory, emsg, msg, f=compile.rule_errors):
            rule = compile.parse1(code_string)
            errs = f(rule, run.theory, theory)
            self.assertTrue(any(emsg in str(err) for err in errs),
                            msg + ":: Failed to find error message '" + emsg +
                            "' in: " + ";".join(str(e) for e in errs))

        # no errors
        rule = compile.parse1('p(x) :- q(x), mod1:p(x, y, z), mod2:q(x, y), '
                              'mod1:q(t), mod2:p(t)')
        errs = compile.rule_errors(rule, run.theory)
        self.assertEqual(len(errs), 0, "Should not have found any errors")

        # unknown table within module
        check_err('p(x) :- q(x), mod1:r(x), r(x)',
                  'mod3',
                  'unknown table',
                  'Unknown table for rule')

        # wrong number of arguments
        check_err('p(x) :- q(x), mod1:p(x,y,z,w), r(x)',
                  'mod3',
                  'only 3 arguments are permitted',
                  'Wrong number of arguments for rule')

        # same tests for an atom

        # no errors
        atom = compile.parse1('p(1, 2, 2)')
        errs = compile.fact_errors(atom, run.theory, 'mod1')
        self.assertEqual(len(errs), 0, "Should not have found any errors")

        # unknown table within module
        check_err('r(1)',
                  'mod1',
                  'unknown table',
                  'Unknown table for atom',
                  f=compile.fact_errors)

        # wrong number of arguments
        check_err('p(1, 2, 3, 4)',
                  'mod1',
                  'only 3 arguments are permitted',
                  'Wrong number of arguments for atom',
                  f=compile.fact_errors)
Ejemplo n.º 13
0
    def test_use_modules(self):
        literal = compile.parse1('nova:p(1)', use_modules=False)
        self.assertEqual(str(literal.table), 'nova:p')
        self.assertIsNone(literal.table.service)

        rule = compile.parse1('nova:q(x) :- neutron:p(x)', use_modules=False)
        self.assertEqual(rule.head.table.table, 'nova:q')
        self.assertEqual(rule.head.table.service, None)
        self.assertEqual(rule.body[0].table.table, 'neutron:p')
        self.assertEqual(rule.body[0].table.service, None)
Ejemplo n.º 14
0
 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('other[s(x)] :- q(x)'))
     self.assertTrue(set(g.tables_with_modal('execute')), set(['p', 'r']))
     g.undo_changes(chgs)
     self.assertTrue(set(g.tables_with_modal('execute')), set(['p']))
Ejemplo n.º 15
0
    def test_empty(self):
        # full empty
        th = nonrecursive.NonrecursiveRuleTheory()
        th.insert(compile.parse1('p(x) :- q(x)'))
        th.insert(compile.parse1('p(1)'))
        th.insert(compile.parse1('q(2)'))
        th.empty()
        self.assertEqual(len(th.content()), 0)

        # empty with tablenames
        th = nonrecursive.NonrecursiveRuleTheory()
        th.insert(compile.parse1('p(x) :- q(x)'))
        th.insert(compile.parse1('p(1)'))
        th.insert(compile.parse1('q(2)'))
        th.empty(['p'])
        e = helper.datalog_equal(th.content_string(), 'q(2)')
        self.assertTrue(e)

        # empty with invert
        th = nonrecursive.NonrecursiveRuleTheory()
        th.insert(compile.parse1('p(x) :- q(x)'))
        th.insert(compile.parse1('p(1)'))
        th.insert(compile.parse1('q(2)'))
        th.empty(['p'], invert=True)
        correct = ('p(x) :- q(x)   p(1)')
        e = helper.datalog_equal(th.content_string(), correct)
        self.assertTrue(e)
Ejemplo n.º 16
0
    def test_empty(self):
        # full empty
        th = NonrecursiveRuleTheory()
        th.insert(compile.parse1('p(x) :- q(x)'))
        th.insert(compile.parse1('p(1)'))
        th.insert(compile.parse1('q(2)'))
        th.empty()
        self.assertEqual(len(th.content()), 0)

        # empty with tablenames
        th = NonrecursiveRuleTheory()
        th.insert(compile.parse1('p(x) :- q(x)'))
        th.insert(compile.parse1('p(1)'))
        th.insert(compile.parse1('q(2)'))
        th.empty(['p'])
        e = helper.datalog_equal(th.content_string(), 'q(2)')
        self.assertTrue(e)

        # empty with invert
        th = NonrecursiveRuleTheory()
        th.insert(compile.parse1('p(x) :- q(x)'))
        th.insert(compile.parse1('p(1)'))
        th.insert(compile.parse1('q(2)'))
        th.empty(['p'], invert=True)
        correct = ('p(x) :- q(x)   p(1)')
        e = helper.datalog_equal(th.content_string(), correct)
        self.assertTrue(e)
Ejemplo n.º 17
0
    def test_empty(self):
        # full empty
        th = nonrecursive.NonrecursiveRuleTheory()
        th.insert(compile.parse1("p(x) :- q(x)"))
        th.insert(compile.parse1("p(1)"))
        th.insert(compile.parse1("q(2)"))
        th.empty()
        self.assertEqual(len(th.content()), 0)

        # empty with tablenames
        th = nonrecursive.NonrecursiveRuleTheory()
        th.insert(compile.parse1("p(x) :- q(x)"))
        th.insert(compile.parse1("p(1)"))
        th.insert(compile.parse1("q(2)"))
        th.empty(["p"])
        e = helper.datalog_equal(th.content_string(), "q(2)")
        self.assertTrue(e)

        # empty with invert
        th = nonrecursive.NonrecursiveRuleTheory()
        th.insert(compile.parse1("p(x) :- q(x)"))
        th.insert(compile.parse1("p(1)"))
        th.insert(compile.parse1("q(2)"))
        th.empty(["p"], invert=True)
        correct = "p(x) :- q(x)   p(1)"
        e = helper.datalog_equal(th.content_string(), correct)
        self.assertTrue(e)
Ejemplo n.º 18
0
    def test_no_split_parsing(self):
        th = NonrecursiveRuleTheory()
        th.insert(compile.parse1('nova:v(x, y) :- u(x, y)',
                                 use_modules=False))

        self.assertEqual(th.arity('nova:v'), 2)
        self.assertIsNone(th.arity('nova:v', modal='insert'))
        th.insert(compile.parse1('insert[neutron:v(x, y, z)] :- u(x, y)',
                                 use_modules=False))
        self.assertEqual(th.arity('nova:v'), 2)
        self.assertEqual(th.arity('neutron:v', modal='insert'), 3)
Ejemplo n.º 19
0
    def test_no_split_parsing(self):
        th = nonrecursive.NonrecursiveRuleTheory()
        th.insert(compile.parse1('nova:v(x, y) :- u(x, y)', use_modules=False))

        self.assertEqual(th.arity('nova:v'), 2)
        self.assertIsNone(th.arity('nova:v', modal='insert'))
        th.insert(
            compile.parse1('insert[neutron:v(x, y, z)] :- u(x, y)',
                           use_modules=False))
        self.assertEqual(th.arity('nova:v'), 2)
        self.assertEqual(th.arity('neutron:v', modal='insert'), 3)
Ejemplo n.º 20
0
 def test_dependency_batch(self):
     obj = self.MyObject()
     run = agnostic.Runtime()
     run.create_policy('test')
     run.insert('p(x) :- q(x)')
     run.register_trigger('p', lambda old, new: obj.increment())
     rule = compile.parse1('q(x) :- r(x)')
     data = compile.parse1('r(1)')
     run.update([compile.Event(rule, target='test'),
                 compile.Event(data, target='test')])
     self.assertEqual(obj.value, 1)
Ejemplo n.º 21
0
 def test_regular_parsing(self):
     th = nonrecursive.NonrecursiveRuleTheory()
     th.insert(compile.parse1('p(x) :- q(x, y)'))
     th.insert(compile.parse1('execute[r(x)] :- t(x, y)'))
     th.insert(compile.parse1('execute[nova:s(x, y)] :- u(x, y)'))
     th.insert(compile.parse1('execute[nova:noargs()] :- true'))
     self.assertEqual(th.arity('p'), 1)
     self.assertIsNone(th.arity('q'))
     self.assertIsNone(th.arity('r'))
     self.assertIsNone(th.arity('nova:s'))
     self.assertEqual(th.arity('r', modal='execute'), 1)
     self.assertEqual(th.arity('nova:s', modal='execute'), 2)
     self.assertEqual(th.arity('nova:noargs', modal='execute'), 0)
Ejemplo n.º 22
0
 def test_regular_parsing(self):
     th = nonrecursive.NonrecursiveRuleTheory()
     th.insert(compile.parse1("p(x) :- q(x, y)"))
     th.insert(compile.parse1("execute[r(x)] :- t(x, y)"))
     th.insert(compile.parse1("execute[nova:s(x, y)] :- u(x, y)"))
     th.insert(compile.parse1("execute[nova:noargs()] :- true"))
     self.assertEqual(th.arity("p"), 1)
     self.assertIsNone(th.arity("q"))
     self.assertIsNone(th.arity("r"))
     self.assertIsNone(th.arity("nova:s"))
     self.assertEqual(th.arity("r", modal="execute"), 1)
     self.assertEqual(th.arity("nova:s", modal="execute"), 2)
     self.assertEqual(th.arity("nova:noargs", modal="execute"), 0)
Ejemplo n.º 23
0
 def test_regular_parsing(self):
     th = NonrecursiveRuleTheory()
     th.insert(compile.parse1('p(x) :- q(x, y)'))
     th.insert(compile.parse1('execute[r(x)] :- t(x, y)'))
     th.insert(compile.parse1('execute[nova:s(x, y)] :- u(x, y)'))
     th.insert(compile.parse1('execute[nova:noargs()] :- true'))
     self.assertEqual(th.arity('p'), 1)
     self.assertIsNone(th.arity('q'))
     self.assertIsNone(th.arity('r'))
     self.assertIsNone(th.arity('nova:s'))
     self.assertEqual(th.arity('r', modal='execute'), 1)
     self.assertEqual(th.arity('nova:s', modal='execute'), 2)
     self.assertEqual(th.arity('nova:noargs', modal='execute'), 0)
Ejemplo n.º 24
0
    def test_discard_rules_with_same_head(self):
        rule1 = compile.parse1('p(x,y) :- q(x), r(y)')
        rule2 = compile.parse1('p(x,y) :- s(x), t(y)')
        self.assertTrue(self.ruleset.add_rule('p', rule1))
        self.assertTrue(self.ruleset.add_rule('p', rule2))
        self.assertTrue('p' in self.ruleset)
        self.assertTrue(rule1 in self.ruleset.get_rules('p'))
        self.assertTrue(rule2 in self.ruleset.get_rules('p'))

        self.assertTrue(self.ruleset.discard_rule('p', rule1))
        self.assertTrue(self.ruleset.discard_rule('p', rule2))
        self.assertFalse('p' in self.ruleset)
        self.assertEqual([], self.ruleset.keys())
Ejemplo n.º 25
0
    def test_discard_rules_with_same_head(self):
        rule1 = compile.parse1('p(x,y) :- q(x), r(y)')
        rule2 = compile.parse1('p(x,y) :- s(x), t(y)')
        self.assertTrue(self.ruleset.add_rule('p', rule1))
        self.assertTrue(self.ruleset.add_rule('p', rule2))
        self.assertTrue('p' in self.ruleset)
        self.assertTrue(rule1 in self.ruleset.get_rules('p'))
        self.assertTrue(rule2 in self.ruleset.get_rules('p'))

        self.assertTrue(self.ruleset.discard_rule('p', rule1))
        self.assertTrue(self.ruleset.discard_rule('p', rule2))
        self.assertFalse('p' in self.ruleset)
        self.assertEqual([], self.ruleset.keys())
Ejemplo n.º 26
0
 def test_dependency_batch(self):
     obj = self.MyObject()
     run = agnostic.Runtime()
     run.create_policy('test')
     run.insert('p(x) :- q(x)')
     run.register_trigger('p', lambda old, new: obj.increment())
     rule = compile.parse1('q(x) :- r(x)')
     data = compile.parse1('r(1)')
     run.update([
         compile.Event(rule, target='test'),
         compile.Event(data, target='test')
     ])
     self.assertEqual(obj.value, 1)
Ejemplo n.º 27
0
    def test_add_rules_with_same_head(self):
        rule1 = compile.parse1('p(x,y) :- q(x), r(y)')
        rule2 = compile.parse1('p(x,y) :- s(x), t(y)')

        self.assertTrue(self.ruleset.add_rule('p', rule1))
        self.assertIn('p', self.ruleset)
        self.assertEqual([rule1], self.ruleset.get_rules('p'))
        self.assertEqual(['p'], self.ruleset.keys())

        self.assertTrue(self.ruleset.add_rule('p', rule2))
        self.assertIn('p', self.ruleset)
        self.assertIn(rule1, self.ruleset.get_rules('p'))
        self.assertIn(rule2, self.ruleset.get_rules('p'))
        self.assertEqual(['p'], self.ruleset.keys())
Ejemplo n.º 28
0
    def test_add_rules_with_same_head(self):
        rule1 = compile.parse1('p(x,y) :- q(x), r(y)')
        rule2 = compile.parse1('p(x,y) :- s(x), t(y)')

        self.assertTrue(self.ruleset.add_rule('p', rule1))
        self.assertIn('p', self.ruleset)
        self.assertEqual([rule1], self.ruleset.get_rules('p'))
        self.assertEqual(['p'], self.ruleset.keys())

        self.assertTrue(self.ruleset.add_rule('p', rule2))
        self.assertIn('p', self.ruleset)
        self.assertIn(rule1, self.ruleset.get_rules('p'))
        self.assertIn(rule2, self.ruleset.get_rules('p'))
        self.assertEqual(['p'], self.ruleset.keys())
Ejemplo n.º 29
0
    def test_add_rules_with_different_head(self):
        rule1 = compile.parse1('p1(x,y) :- q(x), r(y)')
        rule2 = compile.parse1('p2(x,y) :- s(x), t(y)')

        self.assertTrue(self.ruleset.add_rule('p1', rule1))
        self.assertTrue(self.ruleset.add_rule('p2', rule2))

        self.assertTrue('p1' in self.ruleset)
        self.assertEqual([rule1], self.ruleset.get_rules('p1'))
        self.assertTrue('p1' in self.ruleset.keys())

        self.assertTrue('p2' in self.ruleset)
        self.assertEqual([rule2], self.ruleset.get_rules('p2'))
        self.assertTrue('p2' in self.ruleset.keys())
Ejemplo n.º 30
0
    def test_add_rules_with_different_head(self):
        rule1 = compile.parse1('p1(x,y) :- q(x), r(y)')
        rule2 = compile.parse1('p2(x,y) :- s(x), t(y)')

        self.assertTrue(self.ruleset.add_rule('p1', rule1))
        self.assertTrue(self.ruleset.add_rule('p2', rule2))

        self.assertTrue('p1' in self.ruleset)
        self.assertEqual([rule1], self.ruleset.get_rules('p1'))
        self.assertTrue('p1' in self.ruleset.keys())

        self.assertTrue('p2' in self.ruleset)
        self.assertEqual([rule2], self.ruleset.get_rules('p2'))
        self.assertTrue('p2' in self.ruleset.keys())
Ejemplo n.º 31
0
    def test_eliminate_column_references_body_order(self):
        """Test eliminate_column_references preserves order insensitivity."""
        run = agnostic.Runtime()
        run.create_policy('nova')
        schema = compile.Schema({'q': ('id', 'name', 'status'),
                                 'r': ('id', 'age', 'weight')})
        theories = {'nova': self.SchemaWrapper(schema)}

        rule1 = compile.parse1("p(x) :- nova:q(id=x, 2=y), nova:r(id=x)"
                               ).eliminate_column_references(theories)
        rule2 = compile.parse1("p(x) :- nova:r(id=x), nova:q(id=x, 2=y)"
                               ).eliminate_column_references(theories)
        self.assertEqual(rule1, rule2, 'eliminate_column_references failed to '
                                       'preserve order insensitivity')
Ejemplo n.º 32
0
 def check_err(self, input_string, unsafe_lit_strings, msg):
     rule = compile.parse1(input_string)
     try:
         compile.reorder_for_safety(rule)
         self.fail("Failed to raise exception for " + input_string)
     except PolicyException as e:
         errmsg = str(e)
         # parse then print to string so string rep same in err msg
         unsafe_lits = [str(compile.parse1(x)) for x in unsafe_lit_strings]
         missing_lits = [m for m in unsafe_lits
                         if m + " (vars" not in errmsg]
         if len(missing_lits) > 0:
             self.fail(
                 "Unsafe literals {} not reported in error: {}".format(
                     ";".join(missing_lits), errmsg))
Ejemplo n.º 33
0
 def test_old_new_correctness(self):
     obj = self.MyObject()
     run = agnostic.Runtime()
     run.create_policy('test')
     run.insert('p(x) :- q(x)')
     run.insert('q(x) :- r(x), not s(x)')
     run.insert('r(1) r(2) r(3)')
     run.insert('s(2)')
     oldp = set(compile.parse('p(1) p(3)'))
     newp = set(compile.parse('p(1) p(2)'))
     run.register_trigger('p',
                          lambda old, new: obj.equal(oldp, newp, old, new))
     run.update([compile.Event(compile.parse1('s(3)')),
                 compile.Event(compile.parse1('s(2)'), insert=False)])
     self.assertEqual(obj.equals, True)
Ejemplo n.º 34
0
 def check_err(self, input_string, unsafe_lit_strings, msg):
     rule = compile.parse1(input_string)
     try:
         compile.reorder_for_safety(rule)
         self.fail("Failed to raise exception for " + input_string)
     except exception.PolicyException as e:
         errmsg = str(e)
         # parse then print to string so string rep same in err msg
         unsafe_lits = [str(compile.parse1(x)) for x in unsafe_lit_strings]
         missing_lits = [m for m in unsafe_lits
                         if m + " (vars" not in errmsg]
         if len(missing_lits) > 0:
             self.fail(
                 "Unsafe literals {} not reported in error: {}".format(
                     ";".join(missing_lits), errmsg))
Ejemplo n.º 35
0
    def test_error_checking(self):
        """Test error-checking on insertion of rules."""
        code = ("p(x) :- q(x)")
        run = self.prep_runtime(code)
        result = run.get_target(MAT_THEORY).policy()
        self.assertTrue(len(result) == 1)
        self.assertTrue(compile.parse1("p(x) :- q(x)") in result)

        # safety 1
        code = ("p(x) :- not q(x)")
        run = self.prep_runtime("", "** Safety 1 **")
        permitted, changes = run.insert(code, MAT_THEORY)
        self.assertFalse(permitted)

        # safety 2
        code = ("p(x) :- q(y)")
        run = self.prep_runtime("", "** Safety 2 **")
        permitted, changes = run.insert(code, MAT_THEORY)
        self.assertFalse(permitted)

        # TODO(thinrichs): weaken cross-policy recursion restriction
        #   so that we can include recursion within a single theory.
        # recursion into classification theory
        # code = ("p(x) :- p(x)")
        # run = self.prep_runtime("", "** Classification Recursion **")
        # permitted, changes = run.insert(code, MAT_THEORY)
        # self.assertTrue(permitted)

        # stratification into classification theory
        code = ("p(x) :- q(x), not p(x)")
        run = self.prep_runtime("", "** Classification Stratification **")
        permitted, changes = run.insert(code, MAT_THEORY)
        self.assertFalse(permitted)
Ejemplo n.º 36
0
    def test_initialize_tables_dse(self):
        """Test performance of initializing data with DSE and Engine.

        This test populates the tables exported by a datasource driver,
        and then invokes the poll() method to send that data to the
        policy engine.  It tests the amount of time to send tables
        across the DSE and load them into the policy engine.
        """
        MAX_TUPLES = 700
        # install datasource driver we can control
        self.cage.loadModule(
            "TestDriver",
            helper.data_module_path("../tests/datasources/test_driver.py"))
        self.cage.createservice(name="data",
                                moduleName="TestDriver",
                                args=helper.datasource_openstack_args())
        driver = self.cage.service_object('data')
        driver.poll_time = 0
        self.engine.create_policy('data')

        # set return value for datasource driver
        facts = [(1, 2.3, 'foo', 'bar', i, 'a' * 100 + str(i))
                 for i in range(MAX_TUPLES)]
        driver.state = {'p': facts}

        # Send formula to engine (so engine subscribes to data:p)
        policy = self.engine.DEFAULT_THEORY
        formula = compile.parse1(
            'q(1) :- data:p(1, 2.3, "foo", "bar", 1, %s)' % ('a' * 100 + '1'))
        self.api['rule'].publish('policy-update',
                                 [agnostic.Event(formula, target=policy)])

        # Poll data and wait til it arrives at engine
        driver.poll()
        self.wait_til_query_nonempty('q(1)', policy)
Ejemplo n.º 37
0
    def test_clear_ruleset(self):
        rule1 = compile.parse1('p(x,y) :- q(x), r(y)')
        self.ruleset.add_rule('p', rule1)
        self.ruleset.clear()

        self.assertFalse('p' in self.ruleset)
        self.assertEqual([], self.ruleset.keys())
Ejemplo n.º 38
0
    def test_tablename(self):
        """Test correct parsing of tablenames."""
        p = compile.parse1('p(1)')
        self.assertEqual(p.table.table, 'p')
        self.assertIsNone(p.table.modal)
        self.assertIsNone(p.table.service)

        p = compile.parse1('nova:p(1)')
        self.assertEqual(p.table.table, 'p')
        self.assertIsNone(p.table.modal)
        self.assertEqual(p.table.service, 'nova')

        p = compile.parse1('execute[nova:p(1)]')
        self.assertEqual(p.table.table, 'p')
        self.assertEqual(p.table.modal, 'execute')
        self.assertEqual(p.table.service, 'nova')
    def test_initialize_tables_dse(self):
        """Test performance of initializing data with DSE and Engine.

        This test populates the tables exported by a datasource driver,
        and then invokes the poll() method to send that data to the
        policy engine.  It tests the amount of time to send tables
        across the DSE and load them into the policy engine.
        """
        MAX_TUPLES = 700
        # install datasource driver we can control
        self.cage.loadModule("TestDriver", helper.data_module_path("../tests/datasources/test_driver.py"))
        self.cage.createservice(name="data", moduleName="TestDriver", args=helper.datasource_openstack_args())
        driver = self.cage.service_object("data")
        driver.poll_time = 0
        self.engine.create_policy("data")

        # set return value for datasource driver
        facts = [(1, 2.3, "foo", "bar", i, "a" * 100 + str(i)) for i in range(MAX_TUPLES)]
        driver.state = {"p": facts}

        # Send formula to engine (so engine subscribes to data:p)
        policy = self.engine.DEFAULT_THEORY
        formula = compile.parse1('q(1) :- data:p(1, 2.3, "foo", "bar", 1, %s)' % ("a" * 100 + "1"))
        self.api["rule"].publish("policy-update", [compile.Event(formula, target=policy)])

        # Poll data and wait til it arrives at engine
        driver.poll()
        self.wait_til_query_nonempty("q(1)", policy)
Ejemplo n.º 40
0
    def test_clear_ruleset(self):
        rule1 = compile.parse1('p(x,y) :- q(x), r(y)')
        self.ruleset.add_rule('p', rule1)
        self.ruleset.clear()

        self.assertFalse('p' in self.ruleset)
        self.assertEqual([], self.ruleset.keys())
Ejemplo n.º 41
0
 def check_err(code_string, theory, emsg, msg, f=compile.rule_errors):
     rule = compile.parse1(code_string)
     errs = f(rule, run.theory, theory)
     self.assertTrue(
         any(emsg in str(err) for err in errs),
         msg + ":: Failed to find error message '" + emsg + "' in: " +
         ";".join(str(e) for e in errs))
Ejemplo n.º 42
0
    def test_tablename(self):
        """Test correct parsing of tablenames."""
        p = compile.parse1('p(1)')
        self.assertEqual(p.table.table, 'p')
        self.assertIsNone(p.table.modal)
        self.assertIsNone(p.table.service)

        p = compile.parse1('nova:p(1)')
        self.assertEqual(p.table.table, 'p')
        self.assertIsNone(p.table.modal)
        self.assertEqual(p.table.service, 'nova')

        p = compile.parse1('execute[nova:p(1)]')
        self.assertEqual(p.table.table, 'p')
        self.assertEqual(p.table.modal, 'execute')
        self.assertEqual(p.table.service, 'nova')
    def test_initialize_tables_dse(self):
        """Test performance of initializing data with DSE and Engine.

        This test populates the tables exported by a datasource driver,
        and then invokes the poll() method to send that data to the
        policy engine.  It tests the amount of time to send tables
        across the DSE and load them into the policy engine.
        """
        MAX_TUPLES = 700
        # install datasource driver we can control
        kwds = {}
        kwds['name'] = 'data'
        kwds['args'] = helper.datasource_openstack_args()
        kwds['driver'] = 'performance'
        driver = self.cage.create_datasource_service(kwds)
        self.cage.register_service(driver)
        driver.poll_time = 0
        self.engine.create_policy('data')

        # set return value for datasource driver
        facts = [(1, 2.3, 'foo', 'bar', i, 'a'*100 + str(i))
                 for i in range(MAX_TUPLES)]
        driver.state = {'p': facts}

        # Send formula to engine (so engine subscribes to data:p)
        policy = self.engine.DEFAULT_THEORY
        formula = compile.parse1(
            'q(1) :- data:p(1, 2.3, "foo", "bar", 1, %s)' % ('a'*100 + '1'))
        self.engine.process_policy_update(
            [compile.Event(formula, target=policy)])

        # Poll data and wait til it arrives at engine
        driver.poll()
        self.wait_til_query_nonempty('q(1)', policy)
Ejemplo n.º 44
0
    def test_error_checking(self):
        """Test error-checking on insertion of rules."""
        code = ("p(x) :- q(x)")
        run = self.prep_runtime(code)
        result = run.get_target(MAT_THEORY).policy()
        self.assertEqual(1, len(result))
        self.assertIn(compile.parse1("p(x) :- q(x)"), result)

        # safety 1
        code = ("p(x) :- not q(x)")
        run = self.prep_runtime("", "** Safety 1 **")
        permitted, changes = run.insert(code, MAT_THEORY)
        self.assertFalse(permitted)

        # safety 2
        code = ("p(x) :- q(y)")
        run = self.prep_runtime("", "** Safety 2 **")
        permitted, changes = run.insert(code, MAT_THEORY)
        self.assertFalse(permitted)

        # TODO(thinrichs): weaken cross-policy recursion restriction
        #   so that we can include recursion within a single theory.
        # recursion into classification theory
        # code = ("p(x) :- p(x)")
        # run = self.prep_runtime("", "** Classification Recursion **")
        # permitted, changes = run.insert(code, MAT_THEORY)
        # self.assertTrue(permitted)

        # stratification into classification theory
        code = ("p(x) :- q(x), not p(x)")
        run = self.prep_runtime("", "** Classification Stratification **")
        permitted, changes = run.insert(code, MAT_THEORY)
        self.assertFalse(permitted)
Ejemplo n.º 45
0
    def test_eliminate_column_references_body_order(self):
        """Test eliminate_column_references preserves order insensitivity."""
        run = agnostic.Runtime()
        run.create_policy('nova')
        schema = compile.Schema({'q': ('id', 'name', 'status'),
                                 'r': ('id', 'age', 'weight')})
        theories = {'nova': self.SchemaWrapper(schema)}

        rule1 = compile.parse1(
            "p(x) :- nova:q(id=x, 2=y), nova:r(id=x)"
            ).eliminate_column_references_and_pad_positional(theories)
        rule2 = compile.parse1(
            "p(x) :- nova:r(id=x), nova:q(id=x, 2=y)"
            ).eliminate_column_references_and_pad_positional(theories)
        self.assertEqual(rule1, rule2, 'eliminate_column_references failed to '
                                       'preserve order insensitivity')
Ejemplo n.º 46
0
 def insert_rule(self, engine, statement, target=None):
     statement = compile.parse1(statement)
     if target is None:
         e = compile.Event(statement)
     else:
         e = compile.Event(statement, target=target)
     engine.process_policy_update([e])
Ejemplo n.º 47
0
 def insert_rule(self, engine, statement, target=None):
     statement = compile.parse1(statement)
     if target is None:
         e = compile.Event(statement)
     else:
         e = compile.Event(statement, target=target)
     engine.process_policy_update([e])
Ejemplo n.º 48
0
    def test_initialize_tables_dse(self):
        """Test performance of initializing data with DSE and Engine.

        This test populates the tables exported by a datasource driver,
        and then invokes the poll() method to send that data to the
        policy engine.  It tests the amount of time to send tables
        across the DSE and load them into the policy engine.
        """
        MAX_TUPLES = 700
        # install datasource driver we can control
        kwds = {}
        kwds['name'] = 'data'
        kwds['args'] = helper.datasource_openstack_args()
        kwds['driver'] = 'performance'
        driver = self.cage.create_datasource_service(kwds)
        self.cage.register_service(driver)
        driver.poll_time = 0
        self.engine.create_policy('data')

        # set return value for datasource driver
        facts = [(1, 2.3, 'foo', 'bar', i, 'a' * 100 + str(i))
                 for i in range(MAX_TUPLES)]
        driver.state = {'p': facts}

        # Send formula to engine (so engine subscribes to data:p)
        policy = self.engine.DEFAULT_THEORY
        formula = compile.parse1(
            'q(1) :- data:p(1, 2.3, "foo", "bar", 1, %s)' % ('a' * 100 + '1'))
        self.engine.process_policy_update(
            [compile.Event(formula, target=policy)])

        # Poll data and wait til it arrives at engine
        driver.poll()
        self.wait_til_query_nonempty('q(1)', policy)
Ejemplo n.º 49
0
    def test_add_fact(self):
        fact1 = Fact('p', (1, 2, 3))
        equivalent_rule = compile.Rule(compile.parse1('p(1,2,3)'), ())

        self.assertTrue(self.ruleset.add_rule('p', fact1))
        self.assertTrue('p' in self.ruleset)
        self.assertEqual([equivalent_rule], self.ruleset.get_rules('p'))
        self.assertEqual(['p'], self.ruleset.keys())
Ejemplo n.º 50
0
    def test_add_fact(self):
        fact1 = compile.Fact('p', (1, 2, 3))
        equivalent_rule = compile.Rule(compile.parse1('p(1,2,3)'), ())

        self.assertTrue(self.ruleset.add_rule('p', fact1))
        self.assertTrue('p' in self.ruleset)
        self.assertEqual([equivalent_rule], self.ruleset.get_rules('p'))
        self.assertEqual(['p'], self.ruleset.keys())
Ejemplo n.º 51
0
 def test_old_new_correctness(self):
     obj = self.MyObject()
     run = agnostic.Runtime()
     run.create_policy('test')
     run.insert('p(x) :- q(x)')
     run.insert('q(x) :- r(x), not s(x)')
     run.insert('r(1) r(2) r(3)')
     run.insert('s(2)')
     oldp = set(compile.parse('p(1) p(3)'))
     newp = set(compile.parse('p(1) p(2)'))
     run.register_trigger('p',
                          lambda old, new: obj.equal(oldp, newp, old, new))
     run.update([
         compile.Event(compile.parse1('s(3)')),
         compile.Event(compile.parse1('s(2)'), insert=False)
     ])
     self.assertEqual(obj.equals, True)
Ejemplo n.º 52
0
    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']))
Ejemplo n.º 53
0
    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']))
Ejemplo n.º 54
0
    def test_add_equivalent_rule(self):
        # equivalent_rule could be a fact because it has no body, and is
        # ground.
        equivalent_rule = compile.Rule(compile.parse1('p(1,2,3)'), ())

        self.assertTrue(self.ruleset.add_rule('p', equivalent_rule))
        self.assertTrue('p' in self.ruleset)
        self.assertEqual([equivalent_rule], self.ruleset.get_rules('p'))
        self.assertEqual(['p'], self.ruleset.keys())
Ejemplo n.º 55
0
    def test_discard_rule(self):
        rule1 = compile.parse1('p(x,y) :- q(x), r(y)')
        self.assertTrue(self.ruleset.add_rule('p', rule1))
        self.assertTrue('p' in self.ruleset)
        self.assertEqual([rule1], self.ruleset.get_rules('p'))

        self.assertTrue(self.ruleset.discard_rule('p', rule1))
        self.assertFalse('p' in self.ruleset)
        self.assertEqual([], self.ruleset.keys())
Ejemplo n.º 56
0
    def test_add_equivalent_rule(self):
        # equivalent_rule could be a fact because it has no body, and is
        # ground.
        equivalent_rule = compile.Rule(compile.parse1('p(1,2,3)'), ())

        self.assertTrue(self.ruleset.add_rule('p', equivalent_rule))
        self.assertTrue('p' in self.ruleset)
        self.assertEqual([equivalent_rule], self.ruleset.get_rules('p'))
        self.assertEqual(['p'], self.ruleset.keys())
Ejemplo n.º 57
0
        def adjust_for_comparison(rules):
            # compile rule string into rule object
            # replace dict with tuple for sorting
            # 'id' field implicitly dropped if present
            rules = [(compile.parse1(rule['rule']), rule['name'],
                      rule['comment']) for rule in rules]

            # sort lists for comparison
            return sorted(rules)
Ejemplo n.º 58
0
 def test_batch_change(self):
     obj = self.MyObject()
     run = agnostic.Runtime()
     run.create_policy('test')
     run.register_trigger('p', lambda old, new: obj.increment())
     p1 = compile.parse1('p(1)')
     result = run.update([compile.Event(p1, target='test')])
     self.assertTrue(result[0], ("Update failed with errors: " +
                                 ";".join(str(x) for x in result[1])))
     self.assertEqual(obj.value, 1)
Ejemplo n.º 59
0
 def check_err(rule, errmsg, msg):
     rule = compile.parse1(rule)
     try:
         rule.eliminate_column_references(theories)
         self.fail("Failed to throw error {}".format(errmsg))
     except (exception.PolicyException,
             exception.IncompleteSchemaException) as e:
         emsg = "Err messages '{}' should include '{}'".format(
             str(e), errmsg)
         self.assertTrue(errmsg in str(e), msg + ": " + emsg)
Ejemplo n.º 60
0
    def test_rule_validation(self):
        """Test that rules are properly validated."""
        # unsafe var in head
        rule = compile.parse1('p(x) :- q(y)')
        errs = compile.rule_errors(rule)
        self.assertEqual(len(errs), 1)

        # multiple unsafe vars in head
        rule = compile.parse1('p(x,y,z) :- q(w)')
        errs = compile.rule_errors(rule)
        self.assertEqual(len(set([str(x) for x in errs])), 3)

        # unsafe var in negtative literal:
        rule = compile.parse1('p(x) :- q(x), not r(y)')
        errs = compile.rule_errors(rule)
        self.assertEqual(len(set([str(x) for x in errs])), 1)

        # unsafe var in negative literal: ensure head doesn't make safe
        rule = compile.parse1('p(x) :- not q(x)')
        errs = compile.rule_errors(rule)
        self.assertEqual(len(set([str(x) for x in errs])), 1)

        # unsafe var in negative literal:
        #      ensure partial safety not total safety
        rule = compile.parse1('p(x) :- q(x), not r(x,y)')
        errs = compile.rule_errors(rule)
        self.assertEqual(len(set([str(x) for x in errs])), 1)

        # unsafe var in negative literal: ensure double negs doesn't make safe
        rule = compile.parse1('p(x) :- q(x), not r(x,y), not s(x, y)')
        errs = compile.rule_errors(rule)
        self.assertEqual(len(set([str(x) for x in errs])), 1)

        # multiple heads with modal
        rule = compile.parse1('execute[p(x)], r(x) :- q(x)')
        errs = compile.rule_errors(rule)
        self.assertEqual(len(set([str(x) for x in errs])), 1)

        # modal in body
        rule = compile.parse1('p(x) :- execute[q(x)]')
        errs = compile.rule_errors(rule)
        self.assertEqual(len(set([str(x) for x in errs])), 1)

        # keywords
        rule = compile.parse1('equal(x) :- q(x)')
        errs = compile.rule_errors(rule)
        self.assertEqual(len(set([str(x) for x in errs])), 1)