pre-commit hook stylistic changes

pull/1/head
Michael Chisholm 2020-08-13 17:44:42 -04:00
parent 16a8c544ac
commit c21b230edb
11 changed files with 211 additions and 203 deletions

View File

@ -1,18 +1,14 @@
import stix2.pattern_visitor
from stix2.equivalence.patterns.transform import (
ChainTransformer, SettleTransformer
)
from stix2.equivalence.patterns.compare.observation import ( from stix2.equivalence.patterns.compare.observation import (
observation_expression_cmp observation_expression_cmp,
)
from stix2.equivalence.patterns.transform import (
ChainTransformer, SettleTransformer,
) )
from stix2.equivalence.patterns.transform.observation import ( from stix2.equivalence.patterns.transform.observation import (
CanonicalizeComparisonExpressionsTransformer, AbsorptionTransformer, CanonicalizeComparisonExpressionsTransformer,
AbsorptionTransformer, DNFTransformer, FlattenTransformer, OrderDedupeTransformer,
FlattenTransformer,
DNFTransformer,
OrderDedupeTransformer
) )
import stix2.pattern_visitor
# Lazy-initialize # Lazy-initialize
_pattern_canonicalizer = None _pattern_canonicalizer = None
@ -38,7 +34,7 @@ def _get_pattern_canonicalizer():
obs_expr_order = OrderDedupeTransformer() obs_expr_order = OrderDedupeTransformer()
obs_expr_absorb = AbsorptionTransformer() obs_expr_absorb = AbsorptionTransformer()
obs_simplify = ChainTransformer( obs_simplify = ChainTransformer(
obs_expr_flatten, obs_expr_order, obs_expr_absorb obs_expr_flatten, obs_expr_order, obs_expr_absorb,
) )
obs_settle_simplify = SettleTransformer(obs_simplify) obs_settle_simplify = SettleTransformer(obs_simplify)
@ -46,7 +42,7 @@ def _get_pattern_canonicalizer():
_pattern_canonicalizer = ChainTransformer( _pattern_canonicalizer = ChainTransformer(
canonicalize_comp_expr, canonicalize_comp_expr,
obs_settle_simplify, obs_dnf, obs_settle_simplify obs_settle_simplify, obs_dnf, obs_settle_simplify,
) )
return _pattern_canonicalizer return _pattern_canonicalizer
@ -86,12 +82,12 @@ def find_equivalent_patterns(search_pattern, patterns):
patterns patterns
""" """
search_pattern_ast = stix2.pattern_visitor.create_pattern_object( search_pattern_ast = stix2.pattern_visitor.create_pattern_object(
search_pattern search_pattern,
) )
pattern_canonicalizer = _get_pattern_canonicalizer() pattern_canonicalizer = _get_pattern_canonicalizer()
canon_search_pattern_ast, _ = pattern_canonicalizer.transform( canon_search_pattern_ast, _ = pattern_canonicalizer.transform(
search_pattern_ast search_pattern_ast,
) )
for pattern in patterns: for pattern in patterns:
@ -99,7 +95,7 @@ def find_equivalent_patterns(search_pattern, patterns):
canon_pattern_ast, _ = pattern_canonicalizer.transform(pattern_ast) canon_pattern_ast, _ = pattern_canonicalizer.transform(pattern_ast)
result = observation_expression_cmp( result = observation_expression_cmp(
canon_search_pattern_ast, canon_pattern_ast canon_search_pattern_ast, canon_pattern_ast,
) )
if result == 0: if result == 0:

View File

@ -2,6 +2,7 @@
Some generic comparison utility functions. Some generic comparison utility functions.
""" """
def generic_cmp(value1, value2): def generic_cmp(value1, value2):
""" """
Generic comparator of values which uses the builtin '<' and '>' operators. Generic comparator of values which uses the builtin '<' and '>' operators.

View File

@ -3,18 +3,18 @@ Comparison utilities for STIX pattern comparison expressions.
""" """
import base64 import base64
import functools import functools
from stix2.patterns import (
_ComparisonExpression, AndBooleanExpression, OrBooleanExpression,
ListObjectPathComponent, IntegerConstant, FloatConstant, StringConstant,
BooleanConstant, TimestampConstant, HexConstant, BinaryConstant,
ListConstant
)
from stix2.equivalence.patterns.compare import generic_cmp, iter_lex_cmp
from stix2.equivalence.patterns.compare import generic_cmp, iter_lex_cmp
from stix2.patterns import (
AndBooleanExpression, BinaryConstant, BooleanConstant, FloatConstant,
HexConstant, IntegerConstant, ListConstant, ListObjectPathComponent,
OrBooleanExpression, StringConstant, TimestampConstant,
_ComparisonExpression,
)
_COMPARISON_OP_ORDER = ( _COMPARISON_OP_ORDER = (
"=", "!=", "<>", "<", "<=", ">", ">=", "=", "!=", "<>", "<", "<=", ">", ">=",
"IN", "LIKE", "MATCHES", "ISSUBSET", "ISSUPERSET" "IN", "LIKE", "MATCHES", "ISSUBSET", "ISSUPERSET",
) )
@ -23,7 +23,7 @@ _CONSTANT_TYPE_ORDER = (
# treated equally as a generic "number" type. So they aren't in this list. # treated equally as a generic "number" type. So they aren't in this list.
# See constant_cmp(). # See constant_cmp().
StringConstant, BooleanConstant, StringConstant, BooleanConstant,
TimestampConstant, HexConstant, BinaryConstant, ListConstant TimestampConstant, HexConstant, BinaryConstant, ListConstant,
) )
@ -111,11 +111,11 @@ def list_cmp(value1, value2):
# Achieve order-independence by sorting the lists first. # Achieve order-independence by sorting the lists first.
sorted_value1 = sorted( sorted_value1 = sorted(
value1.value, key=functools.cmp_to_key(constant_cmp) value1.value, key=functools.cmp_to_key(constant_cmp),
) )
sorted_value2 = sorted( sorted_value2 = sorted(
value2.value, key=functools.cmp_to_key(constant_cmp) value2.value, key=functools.cmp_to_key(constant_cmp),
) )
result = iter_lex_cmp(sorted_value1, sorted_value2, constant_cmp) result = iter_lex_cmp(sorted_value1, sorted_value2, constant_cmp)
@ -131,7 +131,7 @@ _CONSTANT_COMPARATORS = {
TimestampConstant: generic_constant_cmp, TimestampConstant: generic_constant_cmp,
HexConstant: hex_cmp, HexConstant: hex_cmp,
BinaryConstant: bin_cmp, BinaryConstant: bin_cmp,
ListConstant: list_cmp ListConstant: list_cmp,
} }
@ -214,7 +214,7 @@ def object_path_cmp(path1, path2):
path_vals1 = object_path_to_raw_values(path1) path_vals1 = object_path_to_raw_values(path1)
path_vals2 = object_path_to_raw_values(path2) path_vals2 = object_path_to_raw_values(path2)
result = iter_lex_cmp( result = iter_lex_cmp(
path_vals1, path_vals2, object_path_component_cmp path_vals1, path_vals2, object_path_component_cmp,
) )
return result return result
@ -345,7 +345,7 @@ def comparison_expression_cmp(expr1, expr2):
# This will order according to recursive invocations of this comparator, # This will order according to recursive invocations of this comparator,
# on sub-expressions. # on sub-expressions.
result = iter_lex_cmp( result = iter_lex_cmp(
expr1.operands, expr2.operands, comparison_expression_cmp expr1.operands, expr2.operands, comparison_expression_cmp,
) )
return result return result

View File

@ -3,24 +3,23 @@ Comparison utilities for STIX pattern observation expressions.
""" """
from stix2.equivalence.patterns.compare import generic_cmp, iter_lex_cmp from stix2.equivalence.patterns.compare import generic_cmp, iter_lex_cmp
from stix2.equivalence.patterns.compare.comparison import ( from stix2.equivalence.patterns.compare.comparison import (
comparison_expression_cmp, generic_constant_cmp comparison_expression_cmp, generic_constant_cmp,
) )
from stix2.patterns import ( from stix2.patterns import (
ObservationExpression, AndObservationExpression, OrObservationExpression, AndObservationExpression, FollowedByObservationExpression,
QualifiedObservationExpression, _CompoundObservationExpression, ObservationExpression, OrObservationExpression,
RepeatQualifier, WithinQualifier, StartStopQualifier, QualifiedObservationExpression, RepeatQualifier, StartStopQualifier,
FollowedByObservationExpression WithinQualifier, _CompoundObservationExpression,
) )
_OBSERVATION_EXPRESSION_TYPE_ORDER = ( _OBSERVATION_EXPRESSION_TYPE_ORDER = (
ObservationExpression, AndObservationExpression, OrObservationExpression, ObservationExpression, AndObservationExpression, OrObservationExpression,
FollowedByObservationExpression, QualifiedObservationExpression FollowedByObservationExpression, QualifiedObservationExpression,
) )
_QUALIFIER_TYPE_ORDER = ( _QUALIFIER_TYPE_ORDER = (
RepeatQualifier, WithinQualifier, StartStopQualifier RepeatQualifier, WithinQualifier, StartStopQualifier,
) )
@ -36,7 +35,7 @@ def within_cmp(qual1, qual2):
Compare WITHIN qualifiers. This orders by number of seconds. Compare WITHIN qualifiers. This orders by number of seconds.
""" """
return generic_constant_cmp( return generic_constant_cmp(
qual1.number_of_seconds, qual2.number_of_seconds qual1.number_of_seconds, qual2.number_of_seconds,
) )
@ -48,14 +47,14 @@ def startstop_cmp(qual1, qual2):
return iter_lex_cmp( return iter_lex_cmp(
(qual1.start_time, qual1.stop_time), (qual1.start_time, qual1.stop_time),
(qual2.start_time, qual2.stop_time), (qual2.start_time, qual2.stop_time),
generic_constant_cmp generic_constant_cmp,
) )
_QUALIFIER_COMPARATORS = { _QUALIFIER_COMPARATORS = {
RepeatQualifier: repeats_cmp, RepeatQualifier: repeats_cmp,
WithinQualifier: within_cmp, WithinQualifier: within_cmp,
StartStopQualifier: startstop_cmp StartStopQualifier: startstop_cmp,
} }
@ -84,14 +83,14 @@ def observation_expression_cmp(expr1, expr2):
# If they're simple, use contained comparison expression order # If they're simple, use contained comparison expression order
elif type1 is ObservationExpression: elif type1 is ObservationExpression:
result = comparison_expression_cmp( result = comparison_expression_cmp(
expr1.operand, expr2.operand expr1.operand, expr2.operand,
) )
elif isinstance(expr1, _CompoundObservationExpression): elif isinstance(expr1, _CompoundObservationExpression):
# Both compound, and of same type (and/or/followedby): sort according # Both compound, and of same type (and/or/followedby): sort according
# to contents. # to contents.
result = iter_lex_cmp( result = iter_lex_cmp(
expr1.operands, expr2.operands, observation_expression_cmp expr1.operands, expr2.operands, observation_expression_cmp,
) )
else: # QualifiedObservationExpression else: # QualifiedObservationExpression
@ -112,13 +111,13 @@ def observation_expression_cmp(expr1, expr2):
result = qual_cmp(expr1.qualifier, expr2.qualifier) result = qual_cmp(expr1.qualifier, expr2.qualifier)
else: else:
raise TypeError( raise TypeError(
"Can't compare qualifier type: " + qual1_type.__name__ "Can't compare qualifier type: " + qual1_type.__name__,
) )
if result == 0: if result == 0:
# Same qualifier type and details; use qualified expression order # Same qualifier type and details; use qualified expression order
result = observation_expression_cmp( result = observation_expression_cmp(
expr1.observation_expression, expr2.observation_expression expr1.observation_expression, expr2.observation_expression,
) )
return result return result

View File

@ -2,6 +2,7 @@
Generic AST transformation classes. Generic AST transformation classes.
""" """
class Transformer: class Transformer:
""" """
Base class for AST transformers. Base class for AST transformers.
@ -16,7 +17,7 @@ class Transformer:
is useful in situations where a transformation needs to be repeated is useful in situations where a transformation needs to be repeated
until the AST stops changing. until the AST stops changing.
""" """
raise NotImplemented("transform") raise NotImplementedError("transform")
class ChainTransformer(Transformer): class ChainTransformer(Transformer):

View File

@ -3,18 +3,19 @@ Transformation utilities for STIX pattern comparison expressions.
""" """
import functools import functools
import itertools import itertools
from stix2.equivalence.patterns.compare import iter_in, iter_lex_cmp
from stix2.equivalence.patterns.compare.comparison import (
comparison_expression_cmp,
)
from stix2.equivalence.patterns.transform import Transformer from stix2.equivalence.patterns.transform import Transformer
from stix2.equivalence.patterns.transform.specials import ( from stix2.equivalence.patterns.transform.specials import (
windows_reg_key, ipv4_addr, ipv6_addr ipv4_addr, ipv6_addr, windows_reg_key,
) )
from stix2.patterns import ( from stix2.patterns import (
_BooleanExpression, _ComparisonExpression, AndBooleanExpression, AndBooleanExpression, OrBooleanExpression, ParentheticalExpression,
OrBooleanExpression, ParentheticalExpression _BooleanExpression, _ComparisonExpression,
) )
from stix2.equivalence.patterns.compare.comparison import (
comparison_expression_cmp
)
from stix2.equivalence.patterns.compare import iter_lex_cmp, iter_in
def _dupe_ast(ast): def _dupe_ast(ast):
@ -119,7 +120,7 @@ class ComparisonExpressionTransformer(Transformer):
elif isinstance(ast, _ComparisonExpression): elif isinstance(ast, _ComparisonExpression):
meth = getattr( meth = getattr(
self, "transform_comparison", self.transform_default self, "transform_comparison", self.transform_default,
) )
else: else:
@ -156,7 +157,7 @@ class OrderDedupeTransformer(
:return: The same AST node, but with sorted children :return: The same AST node, but with sorted children
""" """
sorted_children = sorted( sorted_children = sorted(
ast.operands, key=functools.cmp_to_key(comparison_expression_cmp) ast.operands, key=functools.cmp_to_key(comparison_expression_cmp),
) )
deduped_children = [ deduped_children = [
@ -165,13 +166,13 @@ class OrderDedupeTransformer(
# need key wrappers in our ASTs! # need key wrappers in our ASTs!
k.obj for k, _ in itertools.groupby( k.obj for k, _ in itertools.groupby(
sorted_children, key=functools.cmp_to_key( sorted_children, key=functools.cmp_to_key(
comparison_expression_cmp comparison_expression_cmp,
) ),
) )
] ]
changed = iter_lex_cmp( changed = iter_lex_cmp(
ast.operands, deduped_children, comparison_expression_cmp ast.operands, deduped_children, comparison_expression_cmp,
) != 0 ) != 0
ast.operands = deduped_children ast.operands = deduped_children
@ -268,7 +269,7 @@ class AbsorptionTransformer(
# The simple check: is child1 contained in child2? # The simple check: is child1 contained in child2?
if iter_in( if iter_in(
child1, child2.operands, comparison_expression_cmp child1, child2.operands, comparison_expression_cmp,
): ):
to_delete.add(j) to_delete.add(j)
@ -278,7 +279,7 @@ class AbsorptionTransformer(
if all( if all(
iter_in( iter_in(
child1_operand, child2.operands, child1_operand, child2.operands,
comparison_expression_cmp comparison_expression_cmp,
) )
for child1_operand in child1.operands for child1_operand in child1.operands
): ):
@ -326,7 +327,7 @@ class DNFTransformer(ComparisonExpressionTransformer):
# we should ensure each repetition is independent of the # we should ensure each repetition is independent of the
# others. # others.
_dupe_ast(sub_ast) for sub_ast in itertools.chain( _dupe_ast(sub_ast) for sub_ast in itertools.chain(
other_children, prod_seq other_children, prod_seq,
) )
]) ])
for prod_seq in itertools.product(*or_children) for prod_seq in itertools.product(*or_children)

View File

@ -3,23 +3,30 @@ Transformation utilities for STIX pattern observation expressions.
""" """
import functools import functools
import itertools import itertools
from stix2.patterns import (
ObservationExpression, AndObservationExpression, OrObservationExpression, from stix2.equivalence.patterns.compare import iter_in, iter_lex_cmp
QualifiedObservationExpression, _CompoundObservationExpression, from stix2.equivalence.patterns.compare.observation import (
ParentheticalExpression, FollowedByObservationExpression observation_expression_cmp,
) )
from stix2.equivalence.patterns.transform import ( from stix2.equivalence.patterns.transform import (
ChainTransformer, SettleTransformer, Transformer ChainTransformer, SettleTransformer, Transformer,
) )
from stix2.equivalence.patterns.transform.comparison import ( from stix2.equivalence.patterns.transform.comparison import (
FlattenTransformer as CFlattenTransformer, SpecialValueCanonicalization,
OrderDedupeTransformer as COrderDedupeTransformer, )
AbsorptionTransformer as CAbsorptionTransformer, from stix2.equivalence.patterns.transform.comparison import \
DNFTransformer as CDNFTransformer, AbsorptionTransformer as CAbsorptionTransformer
SpecialValueCanonicalization from stix2.equivalence.patterns.transform.comparison import \
DNFTransformer as CDNFTransformer
from stix2.equivalence.patterns.transform.comparison import \
FlattenTransformer as CFlattenTransformer
from stix2.equivalence.patterns.transform.comparison import \
OrderDedupeTransformer as COrderDedupeTransformer
from stix2.patterns import (
AndObservationExpression, FollowedByObservationExpression,
ObservationExpression, OrObservationExpression, ParentheticalExpression,
QualifiedObservationExpression, _CompoundObservationExpression,
) )
from stix2.equivalence.patterns.compare import iter_lex_cmp, iter_in
from stix2.equivalence.patterns.compare.observation import observation_expression_cmp
def _dupe_ast(ast): def _dupe_ast(ast):
@ -52,7 +59,7 @@ def _dupe_ast(ast):
elif isinstance(ast, QualifiedObservationExpression): elif isinstance(ast, QualifiedObservationExpression):
# Don't need to dupe the qualifier object at this point # Don't need to dupe the qualifier object at this point
result = QualifiedObservationExpression( result = QualifiedObservationExpression(
_dupe_ast(ast.observation_expression), ast.qualifier _dupe_ast(ast.observation_expression), ast.qualifier,
) )
elif isinstance(ast, ObservationExpression): elif isinstance(ast, ObservationExpression):
@ -100,7 +107,7 @@ class ObservationExpressionTransformer(Transformer):
AndObservationExpression: "and", AndObservationExpression: "and",
OrObservationExpression: "or", OrObservationExpression: "or",
FollowedByObservationExpression: "followedby", FollowedByObservationExpression: "followedby",
QualifiedObservationExpression: "qualified" QualifiedObservationExpression: "qualified",
} }
def transform(self, ast): def transform(self, ast):
@ -143,7 +150,7 @@ class ObservationExpressionTransformer(Transformer):
else: else:
raise TypeError("Not an observation expression: {}: {}".format( raise TypeError("Not an observation expression: {}: {}".format(
type(ast).__name__, str(ast) type(ast).__name__, str(ast),
)) ))
return result, changed return result, changed
@ -228,7 +235,7 @@ class OrderDedupeTransformer(
def __transform(self, ast): def __transform(self, ast):
sorted_children = sorted( sorted_children = sorted(
ast.operands, key=functools.cmp_to_key(observation_expression_cmp) ast.operands, key=functools.cmp_to_key(observation_expression_cmp),
) )
# Deduping only applies to ORs # Deduping only applies to ORs
@ -236,15 +243,15 @@ class OrderDedupeTransformer(
deduped_children = [ deduped_children = [
key.obj for key, _ in itertools.groupby( key.obj for key, _ in itertools.groupby(
sorted_children, key=functools.cmp_to_key( sorted_children, key=functools.cmp_to_key(
observation_expression_cmp observation_expression_cmp,
) ),
) )
] ]
else: else:
deduped_children = sorted_children deduped_children = sorted_children
changed = iter_lex_cmp( changed = iter_lex_cmp(
ast.operands, deduped_children, observation_expression_cmp ast.operands, deduped_children, observation_expression_cmp,
) != 0 ) != 0
ast.operands = deduped_children ast.operands = deduped_children
@ -376,12 +383,12 @@ class AbsorptionTransformer(
if isinstance( if isinstance(
child2, ( child2, (
AndObservationExpression, AndObservationExpression,
FollowedByObservationExpression FollowedByObservationExpression,
) ),
): ):
# The simple check: is child1 contained in child2? # The simple check: is child1 contained in child2?
if iter_in( if iter_in(
child1, child2.operands, observation_expression_cmp child1, child2.operands, observation_expression_cmp,
): ):
to_delete.add(j) to_delete.add(j)
@ -390,11 +397,11 @@ class AbsorptionTransformer(
elif type(child1) is type(child2): elif type(child1) is type(child2):
if isinstance(child1, AndObservationExpression): if isinstance(child1, AndObservationExpression):
can_simplify = self.__is_contained_and( can_simplify = self.__is_contained_and(
child1.operands, child2.operands child1.operands, child2.operands,
) )
else: # child1 and 2 are followedby nodes else: # child1 and 2 are followedby nodes
can_simplify = self.__is_contained_followedby( can_simplify = self.__is_contained_followedby(
child1.operands, child2.operands child1.operands, child2.operands,
) )
if can_simplify: if can_simplify:
@ -434,7 +441,7 @@ class DNFTransformer(ObservationExpressionTransformer):
distributed_children = [ distributed_children = [
root_type([ root_type([
_dupe_ast(sub_ast) for sub_ast in itertools.chain( _dupe_ast(sub_ast) for sub_ast in itertools.chain(
other_children, prod_seq other_children, prod_seq,
) )
]) ])
for prod_seq in itertools.product(*or_children) for prod_seq in itertools.product(*or_children)
@ -477,7 +484,7 @@ class CanonicalizeComparisonExpressionsTransformer(
comp_special = SpecialValueCanonicalization() comp_special = SpecialValueCanonicalization()
comp_dnf = CDNFTransformer() comp_dnf = CDNFTransformer()
self.__comp_canonicalize = ChainTransformer( self.__comp_canonicalize = ChainTransformer(
comp_special, settle_simplify, comp_dnf, settle_simplify comp_special, settle_simplify, comp_dnf, settle_simplify,
) )
def transform_observation(self, ast): def transform_observation(self, ast):

View File

@ -2,10 +2,10 @@
Some simple comparison expression canonicalization functions. Some simple comparison expression canonicalization functions.
""" """
import socket import socket
from stix2.equivalence.patterns.compare.comparison import (
object_path_to_raw_values
)
from stix2.equivalence.patterns.compare.comparison import (
object_path_to_raw_values,
)
# Values we can use as wildcards in path patterns # Values we can use as wildcards in path patterns
_ANY_IDX = object() _ANY_IDX = object()

View File

@ -2,8 +2,8 @@
import importlib import importlib
import inspect import inspect
from six import text_type
from six import text_type
from stix2patterns.exceptions import ParseException from stix2patterns.exceptions import ParseException
from stix2patterns.grammars.STIXPatternParser import TerminalNode from stix2patterns.grammars.STIXPatternParser import TerminalNode
from stix2patterns.v20.grammars.STIXPatternParser import \ from stix2patterns.v20.grammars.STIXPatternParser import \
@ -261,9 +261,11 @@ class STIXPatternVisitorForSTIX2():
property_path.append(self.instantiate("ListObjectPathComponent", current.property_name, next.getText())) property_path.append(self.instantiate("ListObjectPathComponent", current.property_name, next.getText()))
i += 2 i += 2
elif isinstance(next, IntegerConstant): elif isinstance(next, IntegerConstant):
property_path.append(self.instantiate("ListObjectPathComponent", property_path.append(self.instantiate(
"ListObjectPathComponent",
current.property_name if isinstance(current, BasicObjectPathComponent) else text_type(current), current.property_name if isinstance(current, BasicObjectPathComponent) else text_type(current),
next.value)) next.value,
))
i += 2 i += 2
else: else:
property_path.append(current) property_path.append(current)

View File

@ -1,8 +1,8 @@
import pytest import pytest
from stix2.equivalence.patterns import (
equivalent_patterns, find_equivalent_patterns
)
from stix2.equivalence.patterns import (
equivalent_patterns, find_equivalent_patterns,
)
# # # # # # # #
# # Observation expression equivalence tests # # # # Observation expression equivalence tests # #
@ -13,13 +13,13 @@ from stix2.equivalence.patterns import (
"patt1, patt2", [ "patt1, patt2", [
( (
"[a:b=1] OR [a:b=1]", "[a:b=1] OR [a:b=1]",
"[a:b=1]" "[a:b=1]",
), ),
( (
"[a:b=1] OR [a:b=1] OR [a:b=1]", "[a:b=1] OR [a:b=1] OR [a:b=1]",
"[a:b=1]" "[a:b=1]",
), ),
] ],
) )
def test_obs_dupe_equivalent(patt1, patt2): def test_obs_dupe_equivalent(patt1, patt2):
assert equivalent_patterns(patt1, patt2) assert equivalent_patterns(patt1, patt2)
@ -29,13 +29,13 @@ def test_obs_dupe_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[a:b=1] AND [a:b=1]", "[a:b=1] AND [a:b=1]",
"[a:b=1]" "[a:b=1]",
), ),
( (
"[a:b=1] FOLLOWEDBY [a:b=1]", "[a:b=1] FOLLOWEDBY [a:b=1]",
"[a:b=1]" "[a:b=1]",
), ),
] ],
) )
def test_obs_dupe_not_equivalent(patt1, patt2): def test_obs_dupe_not_equivalent(patt1, patt2):
assert not equivalent_patterns(patt1, patt2) assert not equivalent_patterns(patt1, patt2)
@ -72,8 +72,8 @@ def test_obs_dupe_not_equivalent(patt1, patt2):
( (
"[a:b=1] AND ([a:b=2] AND ([a:b=3] AND [a:b=4])) AND ([a:b=5])", "[a:b=1] AND ([a:b=2] AND ([a:b=3] AND [a:b=4])) AND ([a:b=5])",
"([a:b=1] AND ([a:b=2] AND [a:b=3]) AND ([a:b=4] AND [a:b=5]))", "([a:b=1] AND ([a:b=2] AND [a:b=3]) AND ([a:b=4] AND [a:b=5]))",
) ),
] ],
) )
def test_obs_flatten_equivalent(patt1, patt2): def test_obs_flatten_equivalent(patt1, patt2):
assert equivalent_patterns(patt1, patt2) assert equivalent_patterns(patt1, patt2)
@ -103,7 +103,7 @@ def test_obs_flatten_equivalent(patt1, patt2):
"[a:b=1] FOLLOWEDBY ([a:b=2] FOLLOWEDBY [a:b=3]) WITHIN 2 SECONDS", "[a:b=1] FOLLOWEDBY ([a:b=2] FOLLOWEDBY [a:b=3]) WITHIN 2 SECONDS",
"[a:b=1] WITHIN 2 SECONDS FOLLOWEDBY [a:b=2] FOLLOWEDBY [a:b=3]", "[a:b=1] WITHIN 2 SECONDS FOLLOWEDBY [a:b=2] FOLLOWEDBY [a:b=3]",
), ),
] ],
) )
def test_obs_flatten_not_equivalent(patt1, patt2): def test_obs_flatten_not_equivalent(patt1, patt2):
assert not equivalent_patterns(patt1, patt2) assert not equivalent_patterns(patt1, patt2)
@ -113,21 +113,21 @@ def test_obs_flatten_not_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[a:b=1] AND [a:b=2]", "[a:b=1] AND [a:b=2]",
"[a:b=2] AND [a:b=1]" "[a:b=2] AND [a:b=1]",
), ),
( (
"[a:b=1] OR [a:b=2]", "[a:b=1] OR [a:b=2]",
"[a:b=2] OR [a:b=1]" "[a:b=2] OR [a:b=1]",
), ),
( (
"[a:b=1] OR ([a:b=2] AND [a:b=3])", "[a:b=1] OR ([a:b=2] AND [a:b=3])",
"([a:b=3] AND [a:b=2]) OR [a:b=1]" "([a:b=3] AND [a:b=2]) OR [a:b=1]",
), ),
( (
"[a:b=1] WITHIN 2 SECONDS AND [a:b=2] REPEATS 2 TIMES", "[a:b=1] WITHIN 2 SECONDS AND [a:b=2] REPEATS 2 TIMES",
"[a:b=2] REPEATS 2 TIMES AND [a:b=1] WITHIN 2 SECONDS" "[a:b=2] REPEATS 2 TIMES AND [a:b=1] WITHIN 2 SECONDS",
) ),
] ],
) )
def test_obs_order_equivalent(patt1, patt2): def test_obs_order_equivalent(patt1, patt2):
assert equivalent_patterns(patt1, patt2) assert equivalent_patterns(patt1, patt2)
@ -137,13 +137,13 @@ def test_obs_order_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[a:b=1] FOLLOWEDBY [a:b=2]", "[a:b=1] FOLLOWEDBY [a:b=2]",
"[a:b=2] FOLLOWEDBY [a:b=1]" "[a:b=2] FOLLOWEDBY [a:b=1]",
), ),
( (
"[a:b=1] WITHIN 2 SECONDS AND [a:b=2] REPEATS 2 TIMES", "[a:b=1] WITHIN 2 SECONDS AND [a:b=2] REPEATS 2 TIMES",
"[a:b=1] REPEATS 2 TIMES AND [a:b=2] WITHIN 2 SECONDS" "[a:b=1] REPEATS 2 TIMES AND [a:b=2] WITHIN 2 SECONDS",
) ),
] ],
) )
def test_obs_order_not_equivalent(patt1, patt2): def test_obs_order_not_equivalent(patt1, patt2):
assert not equivalent_patterns(patt1, patt2) assert not equivalent_patterns(patt1, patt2)
@ -153,29 +153,29 @@ def test_obs_order_not_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[a:b=1] OR ([a:b=1] AND [a:b=2])", "[a:b=1] OR ([a:b=1] AND [a:b=2])",
"[a:b=1]" "[a:b=1]",
), ),
( (
"[a:b=1] OR ([a:b=1] FOLLOWEDBY [a:b=2])", "[a:b=1] OR ([a:b=1] FOLLOWEDBY [a:b=2])",
"[a:b=1]" "[a:b=1]",
), ),
( (
"([a:b=3] AND [a:b=1]) OR ([a:b=1] AND [a:b=2] AND [a:b=3])", "([a:b=3] AND [a:b=1]) OR ([a:b=1] AND [a:b=2] AND [a:b=3])",
"[a:b=3] AND [a:b=1]" "[a:b=3] AND [a:b=1]",
), ),
( (
"([a:b=1] FOLLOWEDBY [a:b=3]) OR ([a:b=4] FOLLOWEDBY [a:b=1] FOLLOWEDBY [a:b=2] FOLLOWEDBY [a:b=3])", "([a:b=1] FOLLOWEDBY [a:b=3]) OR ([a:b=4] FOLLOWEDBY [a:b=1] FOLLOWEDBY [a:b=2] FOLLOWEDBY [a:b=3])",
"[a:b=1] FOLLOWEDBY [a:b=3]" "[a:b=1] FOLLOWEDBY [a:b=3]",
), ),
( (
"([a:b=1] FOLLOWEDBY [a:b=2]) OR (([a:b=1] FOLLOWEDBY [a:b=2]) AND [a:b=3])", "([a:b=1] FOLLOWEDBY [a:b=2]) OR (([a:b=1] FOLLOWEDBY [a:b=2]) AND [a:b=3])",
"[a:b=1] FOLLOWEDBY [a:b=2]" "[a:b=1] FOLLOWEDBY [a:b=2]",
), ),
( (
"([a:b=1] AND [a:b=2]) OR (([a:b=1] AND [a:b=2]) FOLLOWEDBY [a:b=3])", "([a:b=1] AND [a:b=2]) OR (([a:b=1] AND [a:b=2]) FOLLOWEDBY [a:b=3])",
"[a:b=1] AND [a:b=2]" "[a:b=1] AND [a:b=2]",
), ),
] ],
) )
def test_obs_absorb_equivalent(patt1, patt2): def test_obs_absorb_equivalent(patt1, patt2):
assert equivalent_patterns(patt1, patt2) assert equivalent_patterns(patt1, patt2)
@ -185,13 +185,13 @@ def test_obs_absorb_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"([a:b=1] AND [a:b=2]) OR ([a:b=2] AND [a:b=3] AND [a:b=4])", "([a:b=1] AND [a:b=2]) OR ([a:b=2] AND [a:b=3] AND [a:b=4])",
"[a:b=1] AND [a:b=2]" "[a:b=1] AND [a:b=2]",
), ),
( (
"([a:b=2] FOLLOWEDBY [a:b=1]) OR ([a:b=1] FOLLOWEDBY [a:b=2] FOLLOWEDBY [a:b=3])", "([a:b=2] FOLLOWEDBY [a:b=1]) OR ([a:b=1] FOLLOWEDBY [a:b=2] FOLLOWEDBY [a:b=3])",
"[a:b=2] FOLLOWEDBY [a:b=1]" "[a:b=2] FOLLOWEDBY [a:b=1]",
) ),
] ],
) )
def test_obs_absorb_not_equivalent(patt1, patt2): def test_obs_absorb_not_equivalent(patt1, patt2):
assert not equivalent_patterns(patt1, patt2) assert not equivalent_patterns(patt1, patt2)
@ -201,29 +201,29 @@ def test_obs_absorb_not_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[a:b=1] AND ([a:b=2] OR [a:b=3])", "[a:b=1] AND ([a:b=2] OR [a:b=3])",
"([a:b=1] AND [a:b=2]) OR ([a:b=1] AND [a:b=3])" "([a:b=1] AND [a:b=2]) OR ([a:b=1] AND [a:b=3])",
), ),
( (
"[a:b=1] FOLLOWEDBY ([a:b=2] OR [a:b=3])", "[a:b=1] FOLLOWEDBY ([a:b=2] OR [a:b=3])",
"([a:b=1] FOLLOWEDBY [a:b=2]) OR ([a:b=1] FOLLOWEDBY [a:b=3])" "([a:b=1] FOLLOWEDBY [a:b=2]) OR ([a:b=1] FOLLOWEDBY [a:b=3])",
), ),
( (
"[a:b=1] AND ([a:b=2] AND ([a:b=3] OR [a:b=4]))", "[a:b=1] AND ([a:b=2] AND ([a:b=3] OR [a:b=4]))",
"([a:b=1] AND [a:b=2] AND [a:b=3]) OR ([a:b=1] AND [a:b=2] AND [a:b=4])" "([a:b=1] AND [a:b=2] AND [a:b=3]) OR ([a:b=1] AND [a:b=2] AND [a:b=4])",
), ),
( (
"[a:b=1] FOLLOWEDBY ([a:b=2] FOLLOWEDBY ([a:b=3] OR [a:b=4]))", "[a:b=1] FOLLOWEDBY ([a:b=2] FOLLOWEDBY ([a:b=3] OR [a:b=4]))",
"([a:b=1] FOLLOWEDBY [a:b=2] FOLLOWEDBY [a:b=3]) OR ([a:b=1] FOLLOWEDBY [a:b=2] FOLLOWEDBY [a:b=4])" "([a:b=1] FOLLOWEDBY [a:b=2] FOLLOWEDBY [a:b=3]) OR ([a:b=1] FOLLOWEDBY [a:b=2] FOLLOWEDBY [a:b=4])",
), ),
( (
"([a:b=1] OR [a:b=2]) AND ([a:b=3] OR [a:b=4])", "([a:b=1] OR [a:b=2]) AND ([a:b=3] OR [a:b=4])",
"([a:b=1] AND [a:b=3]) OR ([a:b=1] AND [a:b=4]) OR ([a:b=2] AND [a:b=3]) OR ([a:b=2] AND [a:b=4])" "([a:b=1] AND [a:b=3]) OR ([a:b=1] AND [a:b=4]) OR ([a:b=2] AND [a:b=3]) OR ([a:b=2] AND [a:b=4])",
), ),
( (
"([a:b=1] OR [a:b=2]) FOLLOWEDBY ([a:b=3] OR [a:b=4])", "([a:b=1] OR [a:b=2]) FOLLOWEDBY ([a:b=3] OR [a:b=4])",
"([a:b=1] FOLLOWEDBY [a:b=3]) OR ([a:b=1] FOLLOWEDBY [a:b=4]) OR ([a:b=2] FOLLOWEDBY [a:b=3]) OR ([a:b=2] FOLLOWEDBY [a:b=4])" "([a:b=1] FOLLOWEDBY [a:b=3]) OR ([a:b=1] FOLLOWEDBY [a:b=4]) OR ([a:b=2] FOLLOWEDBY [a:b=3]) OR ([a:b=2] FOLLOWEDBY [a:b=4])",
), ),
] ],
) )
def test_obs_dnf_equivalent(patt1, patt2): def test_obs_dnf_equivalent(patt1, patt2):
assert equivalent_patterns(patt1, patt2) assert equivalent_patterns(patt1, patt2)
@ -233,17 +233,17 @@ def test_obs_dnf_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[a:b=1] AND [a:b=2]", "[a:b=1] AND [a:b=2]",
"[a:b=1] OR [a:b=2]" "[a:b=1] OR [a:b=2]",
), ),
( (
"[a:b=1] AND ([a:b=2] OR [a:b=3])", "[a:b=1] AND ([a:b=2] OR [a:b=3])",
"([a:b=1] AND [a:b=2]) OR [a:b=3]" "([a:b=1] AND [a:b=2]) OR [a:b=3]",
), ),
( (
"[a:b=1] WITHIN 2 SECONDS", "[a:b=1] WITHIN 2 SECONDS",
"[a:b=1] REPEATS 2 TIMES" "[a:b=1] REPEATS 2 TIMES",
) ),
] ],
) )
def test_obs_not_equivalent(patt1, patt2): def test_obs_not_equivalent(patt1, patt2):
assert not equivalent_patterns(patt1, patt2) assert not equivalent_patterns(patt1, patt2)
@ -258,21 +258,21 @@ def test_obs_not_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[a:b=1 AND a:b=1]", "[a:b=1 AND a:b=1]",
"[a:b=1]" "[a:b=1]",
), ),
( (
"[a:b=1 AND a:b=1 AND a:b=1]", "[a:b=1 AND a:b=1 AND a:b=1]",
"[a:b=1]" "[a:b=1]",
), ),
( (
"[a:b=1 OR a:b=1]", "[a:b=1 OR a:b=1]",
"[a:b=1]" "[a:b=1]",
), ),
( (
"[a:b=1 OR a:b=1 OR a:b=1]", "[a:b=1 OR a:b=1 OR a:b=1]",
"[a:b=1]" "[a:b=1]",
) ),
] ],
) )
def test_comp_dupe_equivalent(patt1, patt2): def test_comp_dupe_equivalent(patt1, patt2):
assert equivalent_patterns(patt1, patt2) assert equivalent_patterns(patt1, patt2)
@ -282,29 +282,29 @@ def test_comp_dupe_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[(a:b=1)]", "[(a:b=1)]",
"[a:b=1]" "[a:b=1]",
), ),
( (
"[(((((a:b=1)))))]", "[(((((a:b=1)))))]",
"[(a:b=1)]" "[(a:b=1)]",
), ),
( (
"[a:b=1 AND (a:b=2 AND a:b=3)]", "[a:b=1 AND (a:b=2 AND a:b=3)]",
"[(a:b=1 AND a:b=2) AND a:b=3]" "[(a:b=1 AND a:b=2) AND a:b=3]",
), ),
( (
"[a:b=1 OR (a:b=2 OR a:b=3)]", "[a:b=1 OR (a:b=2 OR a:b=3)]",
"[(a:b=1 OR a:b=2) OR a:b=3]" "[(a:b=1 OR a:b=2) OR a:b=3]",
), ),
( (
"[(((a:b=1 AND ((a:b=2) AND a:b=3) AND (a:b=4))))]", "[(((a:b=1 AND ((a:b=2) AND a:b=3) AND (a:b=4))))]",
"[a:b=1 AND a:b=2 AND a:b=3 AND a:b=4]" "[a:b=1 AND a:b=2 AND a:b=3 AND a:b=4]",
), ),
( (
"[(((a:b=1 OR ((a:b=2) OR a:b=3) OR (a:b=4))))]", "[(((a:b=1 OR ((a:b=2) OR a:b=3) OR (a:b=4))))]",
"[a:b=1 OR a:b=2 OR a:b=3 OR a:b=4]" "[a:b=1 OR a:b=2 OR a:b=3 OR a:b=4]",
), ),
] ],
) )
def test_comp_flatten_equivalent(patt1, patt2): def test_comp_flatten_equivalent(patt1, patt2):
assert equivalent_patterns(patt1, patt2) assert equivalent_patterns(patt1, patt2)
@ -314,17 +314,17 @@ def test_comp_flatten_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[a:b=1 AND a:b=2]", "[a:b=1 AND a:b=2]",
"[a:b=2 AND a:b=1]" "[a:b=2 AND a:b=1]",
), ),
( (
"[a:b=1 OR a:b=2]", "[a:b=1 OR a:b=2]",
"[a:b=2 OR a:b=1]" "[a:b=2 OR a:b=1]",
), ),
( (
"[(a:b=1 OR a:b=2) AND a:b=3]", "[(a:b=1 OR a:b=2) AND a:b=3]",
"[a:b=3 AND (a:b=2 OR a:b=1)]", "[a:b=3 AND (a:b=2 OR a:b=1)]",
) ),
] ],
) )
def test_comp_order_equivalent(patt1, patt2): def test_comp_order_equivalent(patt1, patt2):
assert equivalent_patterns(patt1, patt2) assert equivalent_patterns(patt1, patt2)
@ -334,21 +334,21 @@ def test_comp_order_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[a:b=1 OR (a:b=1 AND a:b=2)]", "[a:b=1 OR (a:b=1 AND a:b=2)]",
"[a:b=1]" "[a:b=1]",
), ),
( (
"[a:b=1 AND (a:b=1 OR a:b=2)]", "[a:b=1 AND (a:b=1 OR a:b=2)]",
"[a:b=1]" "[a:b=1]",
), ),
( (
"[(a:b=1 AND a:b=2) OR (a:b=3 AND a:b=2 AND a:b=1)]", "[(a:b=1 AND a:b=2) OR (a:b=3 AND a:b=2 AND a:b=1)]",
"[a:b=1 AND a:b=2]" "[a:b=1 AND a:b=2]",
), ),
( (
"[(a:b=1 OR a:b=2) AND (a:b=3 OR a:b=2 OR a:b=1)]", "[(a:b=1 OR a:b=2) AND (a:b=3 OR a:b=2 OR a:b=1)]",
"[a:b=1 OR a:b=2]" "[a:b=1 OR a:b=2]",
) ),
] ],
) )
def test_comp_absorb_equivalent(patt1, patt2): def test_comp_absorb_equivalent(patt1, patt2):
assert equivalent_patterns(patt1, patt2) assert equivalent_patterns(patt1, patt2)
@ -358,25 +358,25 @@ def test_comp_absorb_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[a:b=1 OR (a:b=2 AND a:b=3)]", "[a:b=1 OR (a:b=2 AND a:b=3)]",
"[(a:b=1 OR a:b=2) AND (a:b=1 OR a:b=3)]" "[(a:b=1 OR a:b=2) AND (a:b=1 OR a:b=3)]",
), ),
( (
"[a:b=1 AND (a:b=2 OR a:b=3)]", "[a:b=1 AND (a:b=2 OR a:b=3)]",
"[(a:b=1 AND a:b=2) OR (a:b=1 AND a:b=3)]" "[(a:b=1 AND a:b=2) OR (a:b=1 AND a:b=3)]",
), ),
( (
"[(a:b=1 AND a:b=2) OR (a:b=3 AND a:b=4)]", "[(a:b=1 AND a:b=2) OR (a:b=3 AND a:b=4)]",
"[(a:b=1 OR a:b=3) AND (a:b=1 OR a:b=4) AND (a:b=2 OR a:b=3) AND (a:b=2 OR a:b=4)]" "[(a:b=1 OR a:b=3) AND (a:b=1 OR a:b=4) AND (a:b=2 OR a:b=3) AND (a:b=2 OR a:b=4)]",
), ),
( (
"[(a:b=1 OR a:b=2) AND (a:b=3 OR a:b=4)]", "[(a:b=1 OR a:b=2) AND (a:b=3 OR a:b=4)]",
"[(a:b=1 AND a:b=3) OR (a:b=1 AND a:b=4) OR (a:b=2 AND a:b=3) OR (a:b=2 AND a:b=4)]" "[(a:b=1 AND a:b=3) OR (a:b=1 AND a:b=4) OR (a:b=2 AND a:b=3) OR (a:b=2 AND a:b=4)]",
), ),
( (
"[a:b=1 AND (a:b=2 AND (a:b=3 OR a:b=4))]", "[a:b=1 AND (a:b=2 AND (a:b=3 OR a:b=4))]",
"[(a:b=1 AND a:b=2 AND a:b=3) OR (a:b=1 AND a:b=2 AND a:b=4)]" "[(a:b=1 AND a:b=2 AND a:b=3) OR (a:b=1 AND a:b=2 AND a:b=4)]",
) ),
] ],
) )
def test_comp_dnf_equivalent(patt1, patt2): def test_comp_dnf_equivalent(patt1, patt2):
assert equivalent_patterns(patt1, patt2) assert equivalent_patterns(patt1, patt2)
@ -386,17 +386,17 @@ def test_comp_dnf_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[a:b=1]", "[a:b=1]",
"[a:b=2]" "[a:b=2]",
), ),
( (
"[a:b=1 AND a:b=2]", "[a:b=1 AND a:b=2]",
"[a:b=1 OR a:b=2]" "[a:b=1 OR a:b=2]",
), ),
( (
"[(a:b=1 AND a:b=2) OR a:b=3]", "[(a:b=1 AND a:b=2) OR a:b=3]",
"[a:b=1 AND (a:b=2 OR a:b=3)]" "[a:b=1 AND (a:b=2 OR a:b=3)]",
), ),
] ],
) )
def test_comp_not_equivalent(patt1, patt2): def test_comp_not_equivalent(patt1, patt2):
assert not equivalent_patterns(patt1, patt2) assert not equivalent_patterns(patt1, patt2)
@ -406,41 +406,41 @@ def test_comp_not_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[ipv4-addr:value='1.2.3.4/32']", "[ipv4-addr:value='1.2.3.4/32']",
"[ipv4-addr:value='1.2.3.4']" "[ipv4-addr:value='1.2.3.4']",
), ),
( (
"[ipv4-addr:value='1.2.3.4/24']", "[ipv4-addr:value='1.2.3.4/24']",
"[ipv4-addr:value='1.2.3.0/24']" "[ipv4-addr:value='1.2.3.0/24']",
), ),
( (
"[ipv4-addr:value='1.2.255.4/23']", "[ipv4-addr:value='1.2.255.4/23']",
"[ipv4-addr:value='1.2.254.0/23']" "[ipv4-addr:value='1.2.254.0/23']",
), ),
( (
"[ipv4-addr:value='1.2.255.4/20']", "[ipv4-addr:value='1.2.255.4/20']",
"[ipv4-addr:value='1.2.240.0/20']" "[ipv4-addr:value='1.2.240.0/20']",
), ),
( (
"[ipv4-addr:value='1.2.255.4/0']", "[ipv4-addr:value='1.2.255.4/0']",
"[ipv4-addr:value='0.0.0.0/0']" "[ipv4-addr:value='0.0.0.0/0']",
), ),
( (
"[ipv4-addr:value='01.02.03.04']", "[ipv4-addr:value='01.02.03.04']",
"[ipv4-addr:value='1.2.3.4']" "[ipv4-addr:value='1.2.3.4']",
), ),
( (
"[ipv4-addr:value='1.2.3.4/-5']", "[ipv4-addr:value='1.2.3.4/-5']",
"[ipv4-addr:value='1.2.3.4/-5']" "[ipv4-addr:value='1.2.3.4/-5']",
), ),
( (
"[ipv4-addr:value='1.2.3.4/99']", "[ipv4-addr:value='1.2.3.4/99']",
"[ipv4-addr:value='1.2.3.4/99']" "[ipv4-addr:value='1.2.3.4/99']",
), ),
( (
"[ipv4-addr:value='foo']", "[ipv4-addr:value='foo']",
"[ipv4-addr:value='foo']" "[ipv4-addr:value='foo']",
), ),
] ],
) )
def test_comp_special_canonicalization_ipv4(patt1, patt2): def test_comp_special_canonicalization_ipv4(patt1, patt2):
assert equivalent_patterns(patt1, patt2) assert equivalent_patterns(patt1, patt2)
@ -450,17 +450,17 @@ def test_comp_special_canonicalization_ipv4(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[ipv4-addr:value='1.2.3.4']", "[ipv4-addr:value='1.2.3.4']",
"[ipv4-addr:value='1.2.3.5']" "[ipv4-addr:value='1.2.3.5']",
), ),
( (
"[ipv4-addr:value='1.2.3.4/1']", "[ipv4-addr:value='1.2.3.4/1']",
"[ipv4-addr:value='1.2.3.4/2']" "[ipv4-addr:value='1.2.3.4/2']",
), ),
( (
"[ipv4-addr:value='foo']", "[ipv4-addr:value='foo']",
"[ipv4-addr:value='bar']" "[ipv4-addr:value='bar']",
), ),
] ],
) )
def test_comp_special_canonicalization_ipv4_not_equivalent(patt1, patt2): def test_comp_special_canonicalization_ipv4_not_equivalent(patt1, patt2):
assert not equivalent_patterns(patt1, patt2) assert not equivalent_patterns(patt1, patt2)
@ -470,45 +470,45 @@ def test_comp_special_canonicalization_ipv4_not_equivalent(patt1, patt2):
"patt1, patt2", [ "patt1, patt2", [
( (
"[ipv6-addr:value='1:2:3:4:5:6:7:8/128']", "[ipv6-addr:value='1:2:3:4:5:6:7:8/128']",
"[ipv6-addr:value='1:2:3:4:5:6:7:8']" "[ipv6-addr:value='1:2:3:4:5:6:7:8']",
), ),
( (
"[ipv6-addr:value='1:2:3:4:5:6:7:8/112']", "[ipv6-addr:value='1:2:3:4:5:6:7:8/112']",
"[ipv6-addr:value='1:2:3:4:5:6:7:0/112']" "[ipv6-addr:value='1:2:3:4:5:6:7:0/112']",
), ),
( (
"[ipv6-addr:value='1:2:3:4:5:6:ffff:8/111']", "[ipv6-addr:value='1:2:3:4:5:6:ffff:8/111']",
"[ipv6-addr:value='1:2:3:4:5:6:fffe:0/111']" "[ipv6-addr:value='1:2:3:4:5:6:fffe:0/111']",
), ),
( (
"[ipv6-addr:value='1:2:3:4:5:6:ffff:8/104']", "[ipv6-addr:value='1:2:3:4:5:6:ffff:8/104']",
"[ipv6-addr:value='1:2:3:4:5:6:ff00:0/104']" "[ipv6-addr:value='1:2:3:4:5:6:ff00:0/104']",
), ),
( (
"[ipv6-addr:value='1:2:3:4:5:6:7:8/0']", "[ipv6-addr:value='1:2:3:4:5:6:7:8/0']",
"[ipv6-addr:value='0:0:0:0:0:0:0:0/0']" "[ipv6-addr:value='0:0:0:0:0:0:0:0/0']",
), ),
( (
"[ipv6-addr:value='0001:0000:0000:0000:0000:0000:0000:0001']", "[ipv6-addr:value='0001:0000:0000:0000:0000:0000:0000:0001']",
"[ipv6-addr:value='1::1']" "[ipv6-addr:value='1::1']",
), ),
( (
"[ipv6-addr:value='0000:0000:0000:0000:0000:0000:0000:0000']", "[ipv6-addr:value='0000:0000:0000:0000:0000:0000:0000:0000']",
"[ipv6-addr:value='::']" "[ipv6-addr:value='::']",
), ),
( (
"[ipv6-addr:value='1:2:3:4:5:6:7:8/-5']", "[ipv6-addr:value='1:2:3:4:5:6:7:8/-5']",
"[ipv6-addr:value='1:2:3:4:5:6:7:8/-5']" "[ipv6-addr:value='1:2:3:4:5:6:7:8/-5']",
), ),
( (
"[ipv6-addr:value='1:2:3:4:5:6:7:8/99']", "[ipv6-addr:value='1:2:3:4:5:6:7:8/99']",
"[ipv6-addr:value='1:2:3:4:5:6:7:8/99']" "[ipv6-addr:value='1:2:3:4:5:6:7:8/99']",
), ),
( (
"[ipv6-addr:value='foo']", "[ipv6-addr:value='foo']",
"[ipv6-addr:value='foo']" "[ipv6-addr:value='foo']",
), ),
] ],
) )
def test_comp_special_canonicalization_ipv6(patt1, patt2): def test_comp_special_canonicalization_ipv6(patt1, patt2):
assert equivalent_patterns(patt1, patt2) assert equivalent_patterns(patt1, patt2)
@ -528,7 +528,7 @@ def test_comp_special_canonicalization_ipv6(patt1, patt2):
"[ipv6-addr:value='foo']", "[ipv6-addr:value='foo']",
"[ipv6-addr:value='bar']", "[ipv6-addr:value='bar']",
), ),
] ],
) )
def test_comp_special_canonicalization_ipv6_not_equivalent(patt1, patt2): def test_comp_special_canonicalization_ipv6_not_equivalent(patt1, patt2):
assert not equivalent_patterns(patt1, patt2) assert not equivalent_patterns(patt1, patt2)
@ -548,7 +548,7 @@ def test_comp_special_canonicalization_ipv6_not_equivalent(patt1, patt2):
"[windows-registry-key:values[*].name = 'aaa']", "[windows-registry-key:values[*].name = 'aaa']",
"[windows-registry-key:values[*].name = 'AAA']", "[windows-registry-key:values[*].name = 'AAA']",
), ),
] ],
) )
def test_comp_special_canonicalization_win_reg_key(patt1, patt2): def test_comp_special_canonicalization_win_reg_key(patt1, patt2):
assert equivalent_patterns(patt1, patt2) assert equivalent_patterns(patt1, patt2)
@ -572,7 +572,7 @@ def test_comp_special_canonicalization_win_reg_key(patt1, patt2):
"[windows-registry-key:values[*].data='foo']", "[windows-registry-key:values[*].data='foo']",
"[windows-registry-key:values[*].data='FOO']", "[windows-registry-key:values[*].data='FOO']",
), ),
] ],
) )
def test_comp_special_canonicalization_win_reg_key_not_equivalent(patt1, patt2): def test_comp_special_canonicalization_win_reg_key_not_equivalent(patt1, patt2):
assert not equivalent_patterns(patt1, patt2) assert not equivalent_patterns(patt1, patt2)
@ -591,11 +591,11 @@ def test_find_equivalent_patterns():
"[a:b=1] OR ([a:b=2] AND [a:b=1])", "[a:b=1] OR ([a:b=2] AND [a:b=1])",
"[(a:b=2 OR a:b=1) AND a:b=1]", "[(a:b=2 OR a:b=1) AND a:b=1]",
"[c:d=1]", "[c:d=1]",
"[a:b>1]" "[a:b>1]",
] ]
result = list( result = list(
find_equivalent_patterns(search_pattern, other_patterns) find_equivalent_patterns(search_pattern, other_patterns),
) )
assert result == [ assert result == [

View File

@ -658,6 +658,7 @@ def test_parsing_integer_index():
patt_obj = create_pattern_object("[a:b[1]=2]") patt_obj = create_pattern_object("[a:b[1]=2]")
assert str(patt_obj) == "[a:b[1] = 2]" assert str(patt_obj) == "[a:b[1] = 2]"
# This should never occur, because the first component will always be a property_name, and they should not be quoted. # This should never occur, because the first component will always be a property_name, and they should not be quoted.
def test_parsing_quoted_first_path_component(): def test_parsing_quoted_first_path_component():
patt_obj = create_pattern_object("[a:'b'[1]=2]") patt_obj = create_pattern_object("[a:'b'[1]=2]")