Пример #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")
Пример #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)
Пример #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")
Пример #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)
Пример #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)
Пример #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())
Пример #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())
Пример #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)
Пример #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)
Пример #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)
Пример #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)
Пример #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)
Пример #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)
Пример #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']))
Пример #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)
Пример #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)
Пример #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)
Пример #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)
Пример #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)
Пример #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)
Пример #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)
Пример #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)
Пример #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)
Пример #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())
Пример #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())
Пример #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)
Пример #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())
Пример #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())
Пример #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())
Пример #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())
Пример #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')
Пример #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))
Пример #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)
Пример #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))
Пример #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)
Пример #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)
Пример #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())
Пример #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)
Пример #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())
Пример #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))
Пример #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)
Пример #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)
Пример #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')
Пример #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])
Пример #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])
Пример #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)
Пример #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())
Пример #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())
Пример #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)
Пример #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']))
Пример #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']))
Пример #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())
Пример #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())
Пример #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())
Пример #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)
Пример #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)
Пример #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)
Пример #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)