def _check_criterion(self, criterion_k, criterion_v, payload_lookup): criteria_operator = '' if 'type' in criterion_v: criteria_operator = criterion_v['type'] else: return False if 'pattern' not in criterion_v: criterion_v['pattern'] = None try: matches = payload_lookup.get_value(criterion_k) # pick value if only 1 matches else will end up being an array match. if matches: payload_value = matches[0] if len(matches) > 0 else matches else: payload_value = None except: LOG.exception('Failed transforming criteria key %s', criterion_k) return False criteria_pattern = criterion_v['pattern'] op_func = criteria_operators.get_operator(criteria_operator) try: return op_func(value=payload_value, criteria_pattern=criteria_pattern) except: LOG.exception('There might be a problem with critera in rule %s.', self.rule) return False
def test_regex_fail(self): op = operators.get_operator('regex') self.assertFalse(op('v1_foo', 'v1$'), 'Passed regex.') string = 'fooPONIESbarfooooo' self.assertFalse(op(string, 'ponies'), 'Passed regex.') self.assertFalse(op('1', None), 'Passed regex with None as criteria_pattern.')
def test_icontains(self): op = operators.get_operator('icontains') self.assertTrue(op('hasystack nEEdle haystack', 'needle')) self.assertTrue(op('neeDle', 'NeedlE')) self.assertTrue(op('needlehaystack', 'needle')) self.assertTrue(op('NEEDLE haystack', 'NEEDLE')) self.assertTrue(op('haystackNEEDLE', 'needle')) self.assertTrue(op('haystack needle', 'NEEDLE'))
def test_incontains(self): op = operators.get_operator('incontains') self.assertTrue(op('hasystack needle haystack', 'FOO')) self.assertTrue(op('needle', 'FOO')) self.assertTrue(op('needlehaystack', 'needlex')) self.assertTrue(op('needle haystack', 'needlex')) self.assertTrue(op('haystackneedle', 'needlex')) self.assertTrue(op('haystack needle', 'needlex'))
def test_matchwildcard(self): op = operators.get_operator('matchwildcard') self.assertTrue(op('v1', 'v1'), 'Failed matchwildcard.') self.assertFalse(op('test foo test', 'foo'), 'Failed matchwildcard.') self.assertTrue(op('test foo test', '*foo*'), 'Failed matchwildcard.') self.assertTrue(op('bar', 'b*r'), 'Failed matchwildcard.') self.assertTrue(op('bar', 'b?r'), 'Failed matchwildcard.')
def test_matchwildcard(self): op = operators.get_operator('matchwildcard') self.assertTrue(op('v1', 'v1'), 'Failed matchwildcard.') self.assertFalse(op('test foo test', 'foo'), 'Passed matchwildcard.') self.assertTrue(op('test foo test', '*foo*'), 'Failed matchwildcard.') self.assertTrue(op('bar', 'b*r'), 'Failed matchwildcard.') self.assertTrue(op('bar', 'b?r'), 'Failed matchwildcard.') self.assertFalse(op('1', None), 'Passed matchwildcard with None as criteria_pattern.')
def test_nequals(self): op = operators.get_operator('nequals') self.assertTrue(op('foo', 'bar')) self.assertTrue(op('foo', 'foo1')) self.assertTrue(op('foo', 'FOO')) self.assertTrue(op('True', True)) self.assertTrue(op('None', None)) self.assertFalse(op('True', 'True')) self.assertFalse(op(None, None))
def _check_criterion(self, criterion_k, criterion_v, payload_lookup): if 'type' not in criterion_v: # Comparison operator type not specified, can't perform a comparison return (False, None, None) criteria_operator = criterion_v['type'] criteria_condition = criterion_v.get('condition', None) criteria_pattern = criterion_v.get('pattern', None) # Render the pattern (it can contain a jinja expressions) try: criteria_pattern = self._render_criteria_pattern( criteria_pattern=criteria_pattern, criteria_context=payload_lookup.context ) except Exception as e: msg = ('Failed to render pattern value "%s" for key "%s"' % (criteria_pattern, criterion_k)) LOG.exception(msg, extra=self._base_logger_context) self._create_rule_enforcement(failure_reason=msg, exc=e) return (False, None, None) try: matches = payload_lookup.get_value(criterion_k) # pick value if only 1 matches else will end up being an array match. if matches: payload_value = matches[0] if len(matches) > 0 else matches else: payload_value = None except Exception as e: msg = ('Failed transforming criteria key %s' % criterion_k) LOG.exception(msg, extra=self._base_logger_context) self._create_rule_enforcement(failure_reason=msg, exc=e) return (False, None, None) op_func = criteria_operators.get_operator(criteria_operator) try: if criteria_operator == criteria_operators.SEARCH: result = op_func(value=payload_value, criteria_pattern=criteria_pattern, criteria_condition=criteria_condition, check_function=self._bool_criterion) else: result = op_func(value=payload_value, criteria_pattern=criteria_pattern) except Exception as e: msg = ('There might be a problem with the criteria in rule %s' % (self.rule.ref)) LOG.exception(msg, extra=self._base_logger_context) self._create_rule_enforcement(failure_reason=msg, exc=e) return (False, None, None) return result, payload_value, criteria_pattern
def test_matchregex(self): op = operators.get_operator('matchregex') self.assertTrue(op('v1', 'v1$'), 'Failed matchregex.') # Multi line string, make sure re.DOTALL is used string = '''ponies moar foo bar yeah! ''' self.assertTrue(op(string, '.*bar.*'), 'Failed matchregex.') string = 'foo\r\nponies\nbar\nfooooo' self.assertTrue(op(string, '.*ponies.*'), 'Failed matchregex.')
def test_regex(self): op = operators.get_operator('regex') self.assertTrue(op('v1', 'v1$'), 'Failed regex.') string = 'fooponiesbarfooooo' self.assertTrue(op(string, 'ponies'), 'Failed regex.') # Example with | modifier string = 'apple ponies oranges' self.assertTrue(op(string, '(ponies|unicorns)'), 'Failed regex.') string = 'apple unicorns oranges' self.assertTrue(op(string, '(ponies|unicorns)'), 'Failed regex.') string = 'apple unicorns oranges' self.assertFalse(op(string, '(pikachu|snorlax|charmander)'), 'Failed regex.')
def _check_criterion(self, criterion_k, criterion_v, transform): # No payload or matching criterion_k in the payload therefore cannot apply a criteria. if 'pattern' not in criterion_v or criterion_v['pattern'] is None: return False try: payload_value = transform({'result': '{{' + criterion_k + '}}'}) except: LOG.exception('Failed transforming criteria key %s', criterion_k) return False criteria_operator = '' criteria_pattern = criterion_v['pattern'] if 'type' in criterion_v: criteria_operator = criterion_v['type'] op_func = criteria_operators.get_operator(criteria_operator) return op_func(payload_value['result'], criteria_pattern)
def _check_criterion(self, criterion_k, criterion_v, payload_lookup): if "type" not in criterion_v: # Comparison operator type not specified, can't perform a comparison return False criteria_operator = criterion_v["type"] criteria_pattern = criterion_v.get("pattern", None) # Render the pattern (it can contain a jinja expressions) try: criteria_pattern = self._render_criteria_pattern(criteria_pattern=criteria_pattern) except Exception: LOG.exception( 'Failed to render pattern value "%s" for key "%s"' % (criteria_pattern, criterion_k), extra=self._base_logger_context, ) return False try: matches = payload_lookup.get_value(criterion_k) # pick value if only 1 matches else will end up being an array match. if matches: payload_value = matches[0] if len(matches) > 0 else matches else: payload_value = None except: LOG.exception("Failed transforming criteria key %s", criterion_k, extra=self._base_logger_context) return False op_func = criteria_operators.get_operator(criteria_operator) try: result = op_func(value=payload_value, criteria_pattern=criteria_pattern) except: LOG.exception( "There might be a problem with the criteria in rule %s.", self.rule, extra=self._base_logger_context ) return False return result, payload_value, criteria_pattern
def test_lt(self): op = operators.get_operator('lessthan') self.assertTrue(op(1, 2), 'Failed lessthan.')
def test_gt_fail(self): op = operators.get_operator('greaterthan') self.assertFalse(op(2, 3), 'Passed greaterthan.')
def test_timediff_lt_fail(self): op = operators.get_operator('timediff_lt') self.assertFalse(op('2014-07-01T00:01:01.000000', 10), 'Passed test_timediff_lt.')
def test_timediff_gt_fail(self): op = operators.get_operator('timediff_gt') self.assertFalse(op(date_utils.get_datetime_utc_now().isoformat(), 10), 'Passed test_timediff_gt.')
def test_iendswith_fail(self): op = operators.get_operator("iendswith") self.assertFalse(op("hasystack needle haystack", "NEEDLE")) self.assertFalse(op("a hasystack needle haystack", "a ")) self.assertFalse(op("1", None), "Passed iendswith with None as criteria_pattern.")
def test_nexists(self): op = operators.get_operator('nexists') self.assertFalse(op(False, None), 'Should return False') self.assertFalse(op(1, None), 'Should return False') self.assertFalse(op('foo', None), 'Should return False') self.assertTrue(op(None, None), 'Should return True')
def test_timediff_lt(self): op = operators.get_operator('timediff_lt') self.assertTrue(op(date_utils.get_datetime_utc_now().isoformat(), 10), 'Failed test_timediff_lt.')
def test_ninside(self): op = operators.get_operator("ninside") self.assertFalse(op("a", None), "Should return False") self.assertFalse(op("a", "abc"), "Should return False") self.assertTrue(op("a", "bcd"), "Should return True")
def test_iregex(self): op = operators.get_operator('iregex') self.assertTrue(op('V1', 'v1$'), 'Failed iregex.') string = 'fooPONIESbarfooooo' self.assertTrue(op(string, 'ponies'), 'Failed iregex.')
def test_equals_string(self): op = operators.get_operator('equals') self.assertTrue(op('1', '1'), 'Failed equals.') self.assertTrue(op('', ''), 'Failed equals.')
def test_equals_numeric(self): op = operators.get_operator('equals') self.assertTrue(op(1, 1), 'Failed equals.')
def test_matchregex_fail(self): op = operators.get_operator('matchregex') self.assertFalse(op('v1_foo', 'v1$'), 'Passed matchregex.')
def test_matchregex_case_variants(self): op = operators.get_operator('MATCHREGEX') self.assertTrue(op('v1', 'v1$'), 'Failed matchregex.') op = operators.get_operator('MATCHregex') self.assertTrue(op('v1', 'v1$'), 'Failed matchregex.')
def test_lt_fail(self): op = operators.get_operator('lessthan') self.assertFalse(op(1, 1), 'Passed lessthan.')
def test_gt_str(self): op = operators.get_operator('lessthan') self.assertTrue(op('aba', 'bcb'), 'Failed greaterthan.')
def test_get_operator(self): self.assertTrue(operators.get_operator("equals")) self.assertTrue(operators.get_operator("EQUALS"))
def test_timediff_gt(self): op = operators.get_operator('timediff_gt') self.assertTrue(op('2014-07-01T00:01:01.000000', 1), 'Failed test_timediff_gt.')
def test_get_operator_returns_same_operator_with_different_cases(self): equals = operators.get_operator("equals") EQUALS = operators.get_operator("EQUALS") Equals = operators.get_operator("Equals") self.assertEqual(equals, EQUALS) self.assertEqual(equals, Equals)
def test_regex_fail(self): op = operators.get_operator('regex') self.assertFalse(op('v1_foo', 'v1$'), 'Passed regex.') string = 'fooPONIESbarfooooo' self.assertFalse(op(string, 'ponies'), 'Passed regex.')
def test_get_operator_with_nonexistent_operator(self): with self.assertRaises(Exception): operators.get_operator("weird")
def test_search_with_weird_condition(self): op = operators.get_operator("search") with self.assertRaises(operators.UnrecognizedConditionError): op([], [], "weird", None)
def test_search_any_false(self): op = operators.get_operator("search") called_function_args = [] def record_function_args(criterion_k, criterion_v, payload_lookup): called_function_args.append({ "criterion_k": criterion_k, "criterion_v": criterion_v, "payload_lookup": { "field_name": payload_lookup.get_value("item.field_name")[0], "to_value": payload_lookup.get_value("item.to_value")[0], }, }) return (len(called_function_args) % 2) == 0 payload = [ { "field_name": "Status", "to_value": "Denied", }, { "field_name": "Assigned to", "to_value": "Stanley", }, ] criteria_pattern = { "item.field_name": { "type": "equals", "pattern": "Status", }, "item.to_value": { "type": "equals", "pattern": "Approved", }, } result = op(payload, criteria_pattern, "any", record_function_args) self.assertFalse(result) self.assertEqual( called_function_args, [ # Outer loop: payload -> {'field_name': "Status", 'to_value': "Denied"} { # Inner loop: criterion -> item.field_name: {'type': "equals", 'pattern': "Status"} "criterion_k": "item.field_name", "criterion_v": { "type": "equals", "pattern": "Status", }, "payload_lookup": { "field_name": "Status", "to_value": "Denied", }, }, { # Inner loop: criterion -> item.to_value: {'type': "equals", 'pattern': "Approved"} "criterion_k": "item.to_value", "criterion_v": { "type": "equals", "pattern": "Approved", }, "payload_lookup": { "field_name": "Status", "to_value": "Denied", }, }, # Outer loop: payload -> {'field_name': "Assigned to", 'to_value': "Stanley"} { # Inner loop: criterion -> item.to_value: {'type': "equals", 'pattern': "Approved"} "criterion_k": "item.field_name", "criterion_v": { "type": "equals", "pattern": "Status", }, "payload_lookup": { "field_name": "Assigned to", "to_value": "Stanley", }, }, { # Inner loop: criterion -> item.to_value: {'type': "equals", 'pattern': "Approved"} "criterion_k": "item.to_value", "criterion_v": { "type": "equals", "pattern": "Approved", }, "payload_lookup": { "field_name": "Assigned to", "to_value": "Stanley", }, }, ], )
def test_search_all_true(self): op = operators.get_operator("search") called_function_args = [] def record_function_args(criterion_k, criterion_v, payload_lookup): called_function_args.append({ "criterion_k": criterion_k, "criterion_v": criterion_v, "payload_lookup": { "field_name": payload_lookup.get_value("item.field_name")[0], "to_value": payload_lookup.get_value("item.to_value")[0], }, }) return True payload = [ { "field_name": "Status", "to_value": "Approved", }, { "field_name": "Signed off by", "to_value": "Approved", }, ] criteria_pattern = { "item.field_name": { "type": "startswith", "pattern": "S", }, "item.to_value": { "type": "equals", "pattern": "Approved", }, } result = op(payload, criteria_pattern, "all", record_function_args) self.assertTrue(result) self.assertEqual( called_function_args, [ # Outer loop: payload -> {'field_name': "Status", 'to_value': "Approved"} { # Inner loop: item.field_name -> {'type': "startswith", 'pattern': "S"} "criterion_k": "item.field_name", "criterion_v": { "type": "startswith", "pattern": "S", }, "payload_lookup": { "field_name": "Status", "to_value": "Approved", }, }, { # Inner loop: item.to_value -> {'type': "equals", 'pattern': "Approved"} "criterion_k": "item.to_value", "criterion_v": { "type": "equals", "pattern": "Approved", }, "payload_lookup": { "field_name": "Status", "to_value": "Approved", }, }, # Outer loop: payload -> {'field_name': "Signed off by", 'to_value': "Approved"} { # Inner loop: item.field_name -> {'type': "startswith", 'pattern': "S"} "criterion_k": "item.field_name", "criterion_v": { "type": "startswith", "pattern": "S", }, "payload_lookup": { "field_name": "Signed off by", "to_value": "Approved", }, }, { # Inner loop: item.to_value -> {'type': "equals", 'pattern': "Approved"} "criterion_k": "item.to_value", "criterion_v": { "type": "equals", "pattern": "Approved", }, "payload_lookup": { "field_name": "Signed off by", "to_value": "Approved", }, }, ], )
def test_matchregex_case_variants(self): op = operators.get_operator("MATCHREGEX") self.assertTrue(op("v1", "v1$"), "Failed matchregex.") op = operators.get_operator("MATCHregex") self.assertTrue(op("v1", "v1$"), "Failed matchregex.")
def test_lt_char(self): op = operators.get_operator('lessthan') self.assertTrue(op('a', 'b'), 'Failed lessthan.')
def test_ninside(self): op = operators.get_operator('ninside') self.assertFalse(op('a', None), 'Should return False') self.assertFalse(op('a', 'abc'), 'Should return False') self.assertTrue(op('a', 'bcd'), 'Should return True')
def test_gt(self): op = operators.get_operator('greaterthan') self.assertTrue(op(2, 1), 'Failed greaterthan.')
def test_iendswith(self): op = operators.get_operator("iendswith") self.assertTrue(op("haystack needle haystackEND", "HAYstackend")) self.assertTrue(op("HAYSTACK needle haystackend", "haystackEND"))
def test_matchregex_fail(self): op = operators.get_operator("matchregex") self.assertFalse(op("v1_foo", "v1$"), "Passed matchregex.") self.assertFalse(op("1", None), "Passed matchregex with None as criteria_pattern.")
def test_iregex_fail(self): op = operators.get_operator('iregex') self.assertFalse(op('V1_foo', 'v1$'), 'Passed iregex.')
def test_equals_numeric(self): op = operators.get_operator("equals") self.assertTrue(op(1, 1), "Failed equals.")
def test_iequals_fail(self): op = operators.get_operator("iequals") self.assertFalse(op("ABC", "BCA"), "Passed iequals.") self.assertFalse(op("1", None), "Passed iequals with None as criteria_pattern.")
def test_incontains_fail(self): op = operators.get_operator("incontains") self.assertFalse(op("hasystack needle haystack", "nEeDle")) self.assertFalse(op("needlA", "needlA")) self.assertFalse(op("1", None), "Passed incontains with None as criteria_pattern.")
def test_startswith_fail(self): op = operators.get_operator("startswith") self.assertFalse(op("hasystack needle haystack", "needle")) self.assertFalse(op("a hasystack needle haystack", "haystack")) self.assertFalse(op("1", None), "Passed startswith with None as criteria_pattern.")