def update_would_cause_errors(self, events): """Return a list of PolicyException. Return a list of PolicyException if we were to apply the insert/deletes of policy statements dictated by EVENTS to the current policy. """ self.log(None, "update_would_cause_errors %s", iterstr(events)) errors = [] for event in events: if not compile.is_datalog(event.formula): errors.append(PolicyException( "Non-formula found: {}".format( str(event.formula)))) else: if event.formula.is_atom(): errors.extend(compile.fact_errors( event.formula, self.theories, self.name)) else: errors.extend(compile.rule_errors( event.formula, self.theories, self.name)) # Would also check that rules are non-recursive, but that # is currently being handled by Runtime. The current implementation # disallows recursion in all theories. return errors
def update_would_cause_errors(self, events): """Return a list of PolicyException. Return a list of PolicyException if we were to apply the events EVENTS to the current policy. """ self.log(None, "update_would_cause_errors %s", iterstr(events)) errors = [] for event in events: if not compile.is_datalog(event.formula): errors.append(PolicyException( "Non-formula found: {}".format( str(event.formula)))) else: if event.formula.is_atom(): errors.extend(compile.fact_errors( event.formula, self.theories, self.name)) else: errors.extend(compile.rule_head_has_no_theory( event.formula, permit_head=lambda lit: lit.is_update())) # Should put this back in place, but there are some # exceptions that we don't handle right now. # Would like to mark some tables as only being defined # for certain bound/free arguments and take that into # account when doing error checking. # errors.extend(compile.rule_negation_safety(event.formula)) return errors
def update_would_cause_errors(self, events): """Return a list of PolicyException. Return a list of PolicyException if we were to apply the events EVENTS to the current policy. """ self.log(None, "update_would_cause_errors %s", utility.iterstr(events)) errors = [] for event in events: if not compile.is_datalog(event.formula): errors.append( exception.PolicyException("Non-formula found: {}".format( str(event.formula)))) else: if event.formula.is_atom(): errors.extend( compile.fact_errors(event.formula, self.theories, self.name)) else: errors.extend( compile.rule_head_has_no_theory( event.formula, permit_head=lambda lit: lit.is_update())) # Should put this back in place, but there are some # exceptions that we don't handle right now. # Would like to mark some tables as only being defined # for certain bound/free arguments and take that into # account when doing error checking. # errors.extend(compile.rule_negation_safety(event.formula)) return errors
def update_would_cause_errors(self, events): """Return a list of PolicyException. Return a list of PolicyException if we were to apply the insert/deletes of policy statements dictated by EVENTS to the current policy. """ self.log(None, "update_would_cause_errors %s", utility.iterstr(events)) errors = [] for event in events: if not compile.is_datalog(event.formula): errors.append( exception.PolicyException("Non-formula found: {}".format( str(event.formula)))) else: if event.formula.is_atom(): errors.extend( compile.fact_errors(event.formula, self.theories, self.name)) else: errors.extend( compile.rule_errors(event.formula, self.theories, self.name)) # Would also check that rules are non-recursive, but that # is currently being handled by Runtime. The current implementation # disallows recursion in all theories. return errors
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)
def update_would_cause_errors(self, events): """Return a list of Policyxception. Return a list of PolicyException if we were to apply the events EVENTS to the current policy. """ self.log(None, "update_would_cause_errors %s", utility.iterstr(events)) errors = [] for event in events: if not compile.is_atom(event.formula): errors.append(exception.PolicyException( "Non-atomic formula is not permitted: {}".format( str(event.formula)))) else: errors.extend(compile.fact_errors( event.formula, self.theories, self.name)) return errors
def update_would_cause_errors(self, events): """Return a list of PolicyException. Return a list of PolicyException if we were to apply the events EVENTS to the current policy. """ self.log(None, "update_would_cause_errors %s", utility.iterstr(events)) errors = [] # compute new rule set for event in events: assert compile.is_datalog(event.formula), "update_would_cause_errors operates only on objects" self.log(None, "Updating %s", event.formula) if event.formula.is_atom(): errors.extend(compile.fact_errors(event.formula, self.theories, self.name)) else: errors.extend(compile.rule_errors(event.formula, self.theories, self.name)) return errors
def update_would_cause_errors(self, events): """Return a list of Policyxception. Return a list of PolicyException if we were to apply the events EVENTS to the current policy. """ self.log(None, "update_would_cause_errors %s", utility.iterstr(events)) errors = [] for event in events: if not compile.is_atom(event.formula): errors.append( exception.PolicyException( "Non-atomic formula is not permitted: {}".format( str(event.formula)))) else: errors.extend( compile.fact_errors(event.formula, self.theories, self.name)) return errors
def update_would_cause_errors(self, events): """Return a list of PolicyException. Return a list of PolicyException if we were to apply the events EVENTS to the current policy. """ self.log(None, "update_would_cause_errors %s", iterstr(events)) errors = [] # compute new rule set for event in events: assert compile.is_datalog(event.formula), ( "update_would_cause_errors operates only on objects") self.log(None, "Updating %s", event.formula) if event.formula.is_atom(): errors.extend( compile.fact_errors(event.formula, self.theories, self.name)) else: errors.extend( compile.rule_errors(event.formula, self.theories, self.name)) return errors
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) # schema update schema = compile.Schema() rule1 = compile.parse1('p(x) :- q(x, y)') change1 = schema.update(rule1.head, True) rule2 = compile.parse1('p(x) :- r(x, y)') change2 = schema.update(rule2.head, True) self.assertEqual(schema.count['p'], 2) schema.revert(change2) self.assertEqual(schema.count['p'], 1) schema.revert(change1) self.assertEqual('p' in schema.count, False) schema.update(rule1.head, True) schema.update(rule2.head, True) change1 = schema.update(rule1.head, False) change2 = schema.update(rule2.head, False) self.assertEqual('p' in schema.count, False) schema.revert(change2) self.assertEqual(schema.count['p'], 1) schema.revert(change1) self.assertEqual(schema.count['p'], 2)