def test_order_rewrite_literal(self): "Tests rewrite of literal values" # Model the predicate: # foo < bar or foo >= bar or foo > zip or foo <= zip l = ast.Literal('foo') v = ast.Literal('bar') v2 = ast.Literal('zip') cmp1 = ast.CompareOperator('<', l, v) cmp2 = ast.CompareOperator('>=', l, v) cmp3 = ast.CompareOperator('>', l, v2) cmp4 = ast.CompareOperator('<=', l, v2) or1 = ast.LogicalOperator('or', cmp1, cmp2) or2 = ast.LogicalOperator('or', cmp3, cmp4) or3 = ast.LogicalOperator('or', or1, or2) # Rewrite foo < bar as True name = merge.node_name(cmp1, True) r = compare.order_rewrite(ast.dup(or3), name, cmp1, True) assert isinstance(r.left.left, ast.Constant) assert r.left.left.value == True assert isinstance(r.left.right, ast.Constant) assert r.left.right.value == False assert ASTPattern(or2).matches(r.right) # Rewrite foo < bar as False name = merge.node_name(cmp1, True) r = compare.order_rewrite(ast.dup(or3), name, cmp1, False) assert isinstance(r.left.left, ast.Constant) assert r.left.left.value == False assert isinstance(r.left.right, ast.Constant) assert r.left.right.value == True assert ASTPattern(or2).matches(r.right)
def test_min_change(self): t = ast.Constant(True) f = ast.Constant(False) left = ast.LogicalOperator('or', t, f) right = ast.LogicalOperator('and', t, f) r = ast.LogicalOperator('or', left, right) # First pass will only replace the left and right # with constants, but will not cause 3 changes. r = optimizer.optimize(r, max_pass=10, min_change=3) assert isinstance(r, ast.LogicalOperator) assert isinstance(r.left, ast.Constant) assert r.left.value == True assert isinstance(r.right, ast.Constant) assert r.right.value == False
def test_tile(self): p = tiler.SimplePattern('types:CompareOperator AND op:=', 'types:Literal', 'types:Literal') l1 = ast.Literal('foo') r1 = ast.Literal('bar') n1 = ast.CompareOperator('=', l1, r1) l2 = ast.Literal('zip') r2 = ast.Literal('baz') n2 = ast.CompareOperator('=', l2, r2) n = ast.LogicalOperator('or', n1, n2) i = {'count': 0} def func(pattern, node): assert pattern == p count = i['count'] if count == 0: assert node == n1 if count == 1: assert node == n2 i['count'] += 1 assert n == tiler.tile(n, [p], func) assert i['count'] == 2
def test_rewrite_norm(self): "Test a simple re-write" l = ast.Literal('foo') r = ast.Literal('bar') c = ast.LogicalOperator('or', l, r) name = merge.node_name(c) merge.rewrite_ast(c, name, l, True) assert isinstance(c.left, ast.Constant)
def test_logical_eval4(self): l = ast.Literal("l") r = ast.Literal("r") a = ast.LogicalOperator('or', l, r) res, ctx = a.analyze(MockPred(), {"l": False, "r": True}) assert res assert ctx.literals["l"] == False assert ctx.literals["r"] == True
def test_or_replace(self): "Test OR -> True" t = ast.Constant(True) f = ast.Constant(False) n = ast.LogicalOperator('or', t, f) # Should reduce to True c, r = optimizer.optimization_pass(n) assert c == 1 assert isinstance(r, ast.Constant) assert r.value == True # Should reduce to True n = ast.LogicalOperator('or', f, t) c, r = optimizer.optimization_pass(n) assert c == 1 assert isinstance(r, ast.Constant) assert r.value == True
def test_and_replace(self): "Test AND -> False" t = ast.Constant(True) f = ast.Constant(False) n = ast.LogicalOperator('and', t, f) # Should reduce to False c, r = optimizer.optimization_pass(n) assert c == 1 assert isinstance(r, ast.Constant) assert r.value == False # Should reduce to False n = ast.LogicalOperator('and', f, t) c, r = optimizer.optimization_pass(n) assert c == 1 assert isinstance(r, ast.Constant) assert r.value == False
def test_logical_eval1(self): l = ast.Literal("l") r = ast.Literal("r") a = ast.LogicalOperator('and', l, r) res, ctx = a.analyze(MockPred(), {"l": True, "r": False}) assert not res assert ctx.literals["l"] == True assert ctx.literals["r"] == False assert "Right hand side of AND operator at" in ctx.failed[0]
def test_logical_eval5(self): l = ast.Literal("l") r = ast.Literal("r") a = ast.LogicalOperator('or', l, r) res, ctx = a.analyze(MockPred(), {"l": False}) assert not res assert ctx.literals["l"] == False assert ctx.literals["r"] == ast.Undefined() assert "Both sides of OR operator" in ctx.failed[0]
def test_logical_eval6(self): "Short circuit logic" l = ast.Literal("l") r = ast.Literal("r") a = ast.LogicalOperator('or', l, r) res, ctx = a.analyze(MockPred(), {"l": True}) assert res assert ctx.literals["l"] == True assert "r" not in ctx.literals
def test_logical_eval7(self): "Short circuit logic" l = ast.Literal("l") r = ast.Literal("r") a = ast.LogicalOperator('and', l, r) res, ctx = a.analyze(MockPred(), {"l": False}) assert not res assert ctx.literals["l"] == False assert "r" not in ctx.literals assert "Left hand side" in ctx.failed[0]
def test_select_expr_logical(self): "Checks that a logical operation is not selected" l = ast.Literal('foo') r = ast.Literal('bar') n = ast.LogicalOperator('or', l, r) name = merge.node_name(n) expr = merge.select_rewrite_expression(DEEP, name, [n]) assert expr == l n.left = None expr = merge.select_rewrite_expression(DEEP, name, [n]) assert expr == r
def test_or_dead(self): "Tests removing OR with dead branch" f = ast.Constant(False) l = ast.Literal('foo') v = ast.Number(42) cmp = ast.CompareOperator('=', l, v) n = ast.LogicalOperator('or', f, cmp) # Should reduce to to the compare c, r = optimizer.optimization_pass(n) assert c == 1 assert r is cmp
def test_and_dead_right(self): "Tests removing AND with dead branch, right side" t = ast.Constant(True) l = ast.Literal('foo') v = ast.Number(42) cmp = ast.CompareOperator('=', l, v) n = ast.LogicalOperator('and', cmp, t) # Should reduce to to the compare c, r = optimizer.optimization_pass(n) assert c == 1 assert r is cmp
def test_equality_rewrite_diff_static(self): "Test an equality rewrite with different static values" l = ast.Literal('foo') s = ast.Literal('"test"') s.static = True s.static_val = "test" s1 = ast.Literal('"other"') s1.static = True s1.static_val = "other" cmp1 = ast.CompareOperator('=', l, s) cmp2 = ast.CompareOperator('=', l, s1) or1 = ast.LogicalOperator('or', cmp1, cmp2) # Rewrite foo = "test" as True # Left should be True, right should be False name = merge.node_name(cmp1, True) r = compare.equality_rewrite(ast.dup(or1), name, cmp1, True) assert isinstance(r.left, ast.Constant) assert r.left.value == True assert isinstance(r.right, ast.Constant) assert r.right.value == False # Rewrite foo = "test" as False # Left should be False, right should be same name = merge.node_name(cmp1, True) r = compare.equality_rewrite(ast.dup(or1), name, cmp1, False) assert isinstance(r.left, ast.Constant) assert r.left.value == False assert ASTPattern(cmp2).matches(r.right) # Rewrite foo = "other" as True # Left should be False, right should be True name = merge.node_name(cmp2, True) r = compare.equality_rewrite(ast.dup(or1), name, cmp2, True) assert isinstance(r.left, ast.Constant) assert r.left.value == False assert isinstance(r.right, ast.Constant) assert r.right.value == True # Rewrite foo = "other" as False # Left should be same, right should be False name = merge.node_name(cmp2, True) r = compare.equality_rewrite(ast.dup(or1), name, cmp2, False) assert ASTPattern(cmp1).matches(r.left) assert isinstance(r.right, ast.Constant) assert r.right.value == False
def test_cache(self): l = ast.Literal('foo') v = ast.Number(42) gt1 = ast.CompareOperator('>', l, v) l1 = ast.Literal('foo') v1 = ast.Number(42) gt2 = ast.CompareOperator('>', l1, v1) n = ast.LogicalOperator('or', gt1, gt2) cache.cache_expressions(n) # Both sides should be dedupped assert n.left is n.right assert n.left.cache_id == 0
def test_compact(self): l = ast.Literal('foo') v = ast.Number(42) gt = ast.CompareOperator('>', l, v) l1 = ast.Literal('foo') v1 = ast.Number(42) lt = ast.CompareOperator('<', l1, v1) n = ast.LogicalOperator('or', gt, lt) compact.compact(n) # Literal and number should be de-dupped assert l is n.right.left assert v is n.right.right
def test_equality_rewrite_static(self): "Test an equality rewrite with static values" l = ast.Literal('foo') s = ast.Literal('"test"') s.static = True s.static_val = "test" cmp1 = ast.CompareOperator('=', l, s) cmp2 = ast.CompareOperator('!=', l, s) or1 = ast.LogicalOperator('or', cmp1, cmp2) # Rewrite foo = "test" as True # Left should be True, right should be False name = merge.node_name(cmp1, True) r = compare.equality_rewrite(ast.dup(or1), name, cmp1, True) assert isinstance(r.left, ast.Constant) assert r.left.value == True assert isinstance(r.right, ast.Constant) assert r.right.value == False # Rewrite foo = "test" as False # Left should be False, right should be True name = merge.node_name(cmp1, True) r = compare.equality_rewrite(ast.dup(or1), name, cmp1, False) assert isinstance(r.left, ast.Constant) assert r.left.value == False assert isinstance(r.right, ast.Constant) assert r.right.value == True # Rewrite foo != "test" as True # Left should be False, right should be True name = merge.node_name(cmp2, True) r = compare.equality_rewrite(ast.dup(or1), name, cmp2, True) assert isinstance(r.left, ast.Constant) assert r.left.value == False assert isinstance(r.right, ast.Constant) assert r.right.value == True # Rewrite foo != "test" as False # Left should be False, right should be True name = merge.node_name(cmp2, True) r = compare.equality_rewrite(ast.dup(or1), name, cmp2, False) assert isinstance(r.left, ast.Constant) assert r.left.value == True assert isinstance(r.right, ast.Constant) assert r.right.value == False
def test_equality_rewrite_literals(self): "Test an equality rewrite with different literals" l = ast.Literal('foo') v = ast.Literal('bar') v2 = ast.Literal('baz') cmp1 = ast.CompareOperator('=', l, v) cmp2 = ast.CompareOperator('=', l, v2) or1 = ast.LogicalOperator('or', cmp1, cmp2) # Rewrite foo = bar as True # Left should be True, right should be unchanged name = merge.node_name(cmp1, True) r = compare.equality_rewrite(ast.dup(or1), name, cmp1, True) assert isinstance(r.left, ast.Constant) assert r.left.value == True assert ASTPattern(cmp2).matches(r.right) # Rewrite foo = bar as False # Left should be False, right should be same name = merge.node_name(cmp1, True) r = compare.equality_rewrite(ast.dup(or1), name, cmp1, False) assert isinstance(r.left, ast.Constant) assert r.left.value == False assert ASTPattern(cmp2).matches(r.right) # Rewrite foo = baz as True # Left should be same, right should be True name = merge.node_name(cmp2, True) r = compare.equality_rewrite(ast.dup(or1), name, cmp2, True) assert ASTPattern(cmp1).matches(r.left) assert isinstance(r.right, ast.Constant) assert r.right.value == True # Rewrite foo = baz as False # Left should be same, right should be False name = merge.node_name(cmp2, True) r = compare.equality_rewrite(ast.dup(or1), name, cmp2, False) assert ASTPattern(cmp1).matches(r.left) assert isinstance(r.right, ast.Constant) assert r.right.value == False
def test_names(self): n1 = ast.Literal("foo") assert ("Literal", "foo") == merge.node_name(n1) n2 = ast.Number(12) assert ("Number", 12) == merge.node_name(n2) n3 = ast.Constant(True) assert ("Constant", True) == merge.node_name(n3) n4 = ast.Regex("^tubez$") assert ("Regex", "^tubez$") == merge.node_name(n4) n5 = ast.Undefined() assert "Undefined" == merge.node_name(n5) n6 = ast.Empty() assert "Empty" == merge.node_name(n6) # Negate does not emit the operator! n7 = ast.NegateOperator(n3) assert ("Constant", True) == merge.node_name(n7) n8 = ast.CompareOperator('=', n1, n2) n8_name = merge.node_name(n8) assert ("CompareOperator", "=", ("Literal", "foo"), ("Number", 12)) == n8_name n8_static = merge.node_name(n8, True) assert ("CompareOperator", "equality", ("Literal", "foo"), ("Number", "static")) == n8_static n9 = ast.MatchOperator(n1, n4) n9_name = merge.node_name(n9) assert ("MatchOperator", ("Literal", "foo"), ("Regex", "^tubez$")) == n9_name n10 = ast.ContainsOperator(n1, n2) n10_name = merge.node_name(n10) assert ("ContainsOperator", ("Literal", "foo"), ("Number", 12.0)) == n10_name # Logical operator returns literal! n11 = ast.LogicalOperator('and', n1, n3) n11_name = merge.node_name(n11) assert ("Literal", "foo") == n11_name # Literal set just uses name n12 = ast.LiteralSet([n1, n2]) n12_name = merge.node_name(n12) assert "LiteralSet" == n12_name
def test_names(self): n1 = ast.Literal("foo") assert ("Literal", "foo") == compact.node_name(n1) n2 = ast.Number(12) assert ("Number", 12) == compact.node_name(n2) n3 = ast.Constant(True) assert ("Constant", True) == compact.node_name(n3) n4 = ast.Regex("^tubez$") assert ("Regex", "^tubez$") == compact.node_name(n4) n5 = ast.Undefined() assert "Undefined" == compact.node_name(n5) n6 = ast.Empty() assert "Empty" == compact.node_name(n6) n7 = ast.NegateOperator(n3) assert ("NegateOperator", ("Constant", True)) == compact.node_name(n7) n8 = ast.CompareOperator('=', n1, n2) n8_name = compact.node_name(n8) assert ("CompareOperator", "=", ("Literal", "foo"), ("Number", 12)) == n8_name n9 = ast.MatchOperator(n1, n4) n9_name = compact.node_name(n9) assert ("MatchOperator", ("Literal", "foo"), ("Regex", "^tubez$")) == n9_name n10 = ast.ContainsOperator(n1, n2) n10_name = compact.node_name(n10) assert ("ContainsOperator", ("Literal", "foo"), ("Number", 12.0)) == n10_name n11 = ast.LogicalOperator('and', n1, n3) n11_name = compact.node_name(n11) assert ("LogicalOperator", "and", ("Literal", "foo"), ("Constant", True)) == n11_name
def test_bad_child(self): c = ast.CompareOperator("!", ast.Literal("foo"), ast.Empty()) a = ast.LogicalOperator("and", ast.Literal("foo"), c) valid, info = a.validate() assert not valid assert "Unknown compare" in info["errors"][0]
def test_bad_logic(self): a = ast.LogicalOperator("!", ast.Literal("foo"), ast.Empty()) valid, info = a.validate() assert not valid assert "Unknown logical" in info["errors"][0]
def test_order_rewrite_numeric(self): "Tests rewrite of numeric values" # Model the predicate: # foo < 25 or foo >= 50 or foo > 75 or foo <= 100 l = ast.Literal('foo') v = ast.Number(25) v1 = ast.Number(50) v2 = ast.Number(75) v3 = ast.Number(100) cmp1 = ast.CompareOperator('<', l, v) cmp2 = ast.CompareOperator('>=', l, v1) cmp3 = ast.CompareOperator('>', l, v2) cmp4 = ast.CompareOperator('<=', l, v3) or1 = ast.LogicalOperator('or', cmp1, cmp2) or2 = ast.LogicalOperator('or', cmp3, cmp4) or3 = ast.LogicalOperator('or', or1, or2) # Rewrite foo < 25 as true name = merge.node_name(cmp1, True) r = compare.order_rewrite(ast.dup(or3), name, cmp1, True) assert isinstance(r.left.left, ast.Constant) assert r.left.left.value == True assert isinstance(r.left.right, ast.Constant) assert r.left.right.value == False assert isinstance(r.right.left, ast.Constant) assert r.right.left.value == False assert isinstance(r.right.right, ast.Constant) assert r.right.right.value == True # Rewrite foo < 25 as false name = merge.node_name(cmp1, True) r = compare.order_rewrite(ast.dup(or3), name, cmp1, False) assert isinstance(r.left.left, ast.Constant) assert r.left.left.value == False # other cmps unchanges assert ASTPattern(cmp2).matches(r.left.right) assert ASTPattern(cmp3).matches(r.right.left) assert ASTPattern(cmp4).matches(r.right.right) # Rewrite foo >= 50 as true name = merge.node_name(cmp2, True) r = compare.order_rewrite(ast.dup(or3), name, cmp2, True) assert isinstance(r.left.left, ast.Constant) assert r.left.left.value == False assert isinstance(r.left.right, ast.Constant) assert r.left.right.value == True assert ASTPattern(cmp3).matches(r.right.left) assert ASTPattern(cmp4).matches(r.right.right) # Rewrite foo >= 50 as false name = merge.node_name(cmp2, True) r = compare.order_rewrite(ast.dup(or3), name, cmp2, False) assert ASTPattern(cmp1).matches(r.left.left) assert isinstance(r.left.right, ast.Constant) assert r.left.right.value == False assert isinstance(r.right.left, ast.Constant) assert r.right.left.value == False assert isinstance(r.right.right, ast.Constant) assert r.right.right.value == True # Rewrite foo > 75 as true name = merge.node_name(cmp3, True) r = compare.order_rewrite(ast.dup(or3), name, cmp3, True) assert isinstance(r.left.left, ast.Constant) assert r.left.left.value == False assert isinstance(r.left.right, ast.Constant) assert r.left.right.value == True assert isinstance(r.right.left, ast.Constant) assert r.right.left.value == True assert ASTPattern(cmp4).matches(r.right.right) # Rewrite foo > 75 as False name = merge.node_name(cmp3, True) r = compare.order_rewrite(ast.dup(or3), name, cmp3, False) assert ASTPattern(cmp1).matches(r.left.left) assert ASTPattern(cmp2).matches(r.left.right) assert isinstance(r.right.left, ast.Constant) assert r.right.left.value == False assert isinstance(r.right.right, ast.Constant) assert r.right.right.value == True # Rewrite foo <= 100 as True name = merge.node_name(cmp4, True) r = compare.order_rewrite(ast.dup(or3), name, cmp4, True) assert ASTPattern(cmp1).matches(r.left.left) assert ASTPattern(cmp2).matches(r.left.right) assert ASTPattern(cmp3).matches(r.right.left) assert isinstance(r.right.right, ast.Constant) assert r.right.right.value == True # Rewrite foo <= 100 as False name = merge.node_name(cmp4, True) r = compare.order_rewrite(ast.dup(or3), name, cmp4, False) assert isinstance(r.left.left, ast.Constant) assert r.left.left.value == False assert isinstance(r.left.right, ast.Constant) assert r.left.right.value == True assert isinstance(r.right.left, ast.Constant) assert r.right.left.value == True assert isinstance(r.right.right, ast.Constant) assert r.right.right.value == False