def test_valtype_from_different_ctx(): ctx1 = bitblaster.ExprContext(load_defaults=False) ctx1.load_valtype('bitblaster.valtype.bool') ctx2 = bitblaster.ExprContext(load_defaults=False) ctx2.load_valtype('bitblaster.valtype.bool') # Check we can't create a variable in ctx1 with valtype from ctx2. with pytest.raises( RuntimeError, match= r"valtype argument of constant \('bool'\) was created in a different context" ): bool1 = ctx1.constant(value='bool1', valtype=ctx2.valtype.bool())
def test_logical_xnor(): ctx = bitblaster.ExprContext() # Test with two inputs. inputs = [ctx.valtype.bool(), ctx.valtype.bool()] output = lambda op0, op1: op0 == op1 ExprTester(ctx, ctx.expr.logical_xnor, inputs, {}, output)
def test_logical_or(): ctx = bitblaster.ExprContext() v1 = ctx.variable(name='v1', valtype=ctx.valtype.bool()) v2 = ctx.variable(name='v2', valtype=ctx.valtype.bool()) true = ctx.constant(value=1, valtype=ctx.valtype.bool()) false = ctx.constant(value=0, valtype=ctx.valtype.bool()) # Can't simplify two variable ops. expr = ctx.expr.logical_or(v1, v2) assert (ctx.util.simplify(expr) == expr) # logical_or(v1, true) => true expr = ctx.expr.logical_or(v1, true) assert (ctx.util.simplify(expr) == true) # logical_or(false, false) => false expr = ctx.expr.logical_or(false, false) assert (ctx.util.simplify(expr) == false) # logical_or(false, v1) => v1 expr = ctx.expr.logical_or(false, v1) assert (ctx.util.simplify(expr) == v1) # logical_or(v1) => v1 expr = ctx.expr.logical_or(v1) assert (ctx.util.simplify(expr) == v1) # logical_and(logical_not(v1), v1) => true expr = ctx.expr.logical_or(ctx.expr.logical_not(v1), v1) assert (ctx.util.simplify(expr) == true)
def test_logical_not(): ctx = bitblaster.ExprContext() # Test with one input. inputs = [ctx.valtype.bool()] output = lambda op0: not op0 ExprTester(ctx, ctx.expr.logical_not, inputs, {}, output)
def test_logical_implies(): ctx = bitblaster.ExprContext() # Test with two inputs. inputs = [ctx.valtype.bool(), ctx.valtype.bool()] output = lambda op0, op1: not op0 or op1 ExprTester(ctx, ctx.expr.logical_implies, inputs, {}, output)
def test_util_index(): ctx = bitblaster.ExprContext() # Test with a bitvector. inputs = [ctx.valtype.bitvector(width=4)] output = lambda op0: (op0 >> 3) & 1 == 1 attrs = {'index':3} ExprTester(ctx, ctx.expr.util_index, inputs, attrs, output)
def test_bitvector_mult(): ctx = bitblaster.ExprContext() # # Test with two 3-bit bitvectors inputs = [ctx.valtype.bitvector(width=3), ctx.valtype.bitvector(width=3)] output = lambda op0, op1: op0 * op1 attrs = {'width': 6} ExprTester(ctx, ctx.expr.bitvector_mult, inputs, attrs, output)
def test_util_equal(): ctx = bitblaster.ExprContext() # Test with a bitvector. inputs = [ctx.valtype.bitvector(width=2), ctx.valtype.bitvector(width=2)] output = lambda op0, op1: op0 == op1 attrs = {} ExprTester(ctx, ctx.expr.util_equal, inputs, attrs, output)
def test_invalid_value(): ctx = bitblaster.ExprContext(load_defaults=False) ctx.load_valtype('bitblaster.valtype.bool') # Check we can't use some random object for value. with pytest.raises(RuntimeError, match=r"'3' is not a valid value for valtype 'bool'"): bool1 = ctx.constant(value=3, valtype=ctx.valtype.bool())
def test_invalid_name(): ctx = bitblaster.ExprContext(load_defaults=False) ctx.load_valtype('bitblaster.valtype.bool') # Check we can't use some random object for name. with pytest.raises(RuntimeError, match=r"name argument of variable is not a 'str'"): bool1 = ctx.variable(name=1, valtype=ctx.valtype.bool())
def test_load(): ctx = bitblaster.ExprContext(load_defaults=False) ctx.load_valtype('bitblaster.valtype.bitvector') # Test we can create a bitvector valtype. bv1 = ctx.valtype.bitvector(width=10) # Test that the context agrees it's a bitvector. assert (ctx.valtype.is_bitvector(bv1)) # Test that the context agrees it's a bitvector of width 10. assert (ctx.valtype.is_bitvector(bv1, width=10)) # Test that the context agrees it's not a bitvector of width 11. assert (not ctx.valtype.is_bitvector(bv1, width=11)) # Test it's equal to itself. assert (bv1 == bv1) # Test it's not not unequal to itself. assert (not (bv1 != bv1)) # Test calling with non-Valtype objects results in exception. with pytest.raises( RuntimeError, match= r"'is_bitvector' argument \('1'\) is not a bitblaster.Valtype object" ): assert (not ctx.valtype.is_bitvector(1)) with pytest.raises( RuntimeError, match= r"'is_bitvector' argument \('False'\) is not a bitblaster.Valtype object" ): assert (not ctx.valtype.is_bitvector(False)) # Test if we create another bitvector of the same width it's the same object. bv2 = ctx.valtype.bitvector(width=10) assert (id(bv1) == id(bv2)) # Test if we create another bitvector of a different width it's another object. bv2 = ctx.valtype.bitvector(width=8) assert (id(bv1) != id(bv2)) # Test __str__ and __repr__. assert ("bitvector(width=10)" == str(bv1)) assert ("bitvector(width=10)" == repr(bv1)) # Test a boolean isn't mistaken for a bitvector and vice versa. ctx.load_valtype('bitblaster.valtype.bool') assert (not ctx.valtype.is_bool(bv1)) bool1 = ctx.valtype.bool() assert (not ctx.valtype.is_bitvector(bool1)) # Test values. bv2 = ctx.valtype.bitvector(width=2) bv3 = ctx.valtype.bitvector(width=3) bv4 = ctx.valtype.bitvector(width=4) assert (list(bv2.values()) == [0, 1, 2, 3]) assert (list(bv3.values()) == [0, 1, 2, 3, 4, 5, 6, 7]) assert (list(bv4.values()) == [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ])
def test_invalid_valtype(): ctx = bitblaster.ExprContext(load_defaults=False) ctx.load_valtype('bitblaster.valtype.bool') # Check we can't use some random object for valtype. with pytest.raises( RuntimeError, match= r"valtype argument of variable 'bool1' \('1'\) is not a bitblaster.Valtype object" ): bool1 = ctx.variable(name='bool1', valtype=1)
def test_sat3(): ctx = bitblaster.ExprContext(load_defaults=False) ctx.load_expr_def_set('bitblaster.exprdefset.logical')# a = ctx.variable(name="a", valtype=ctx.valtype.bool()) ctx.add_constraint(ctx.expr.logical_and(a, ctx.expr.logical_not(a))) result = ctx.util.solve() # Is not satisfiable. assert(not result)
def test_bitvector_from_bool(): ctx = bitblaster.ExprContext() # def bool_to_int(boolval): return 1 if boolval else 0 # Test with three bools inputs = [ctx.valtype.bool(), ctx.valtype.bool(), ctx.valtype.bool()] output = lambda op0, op1, op2: bool_to_int(op0) + (bool_to_int( op1) << 1) + (bool_to_int(op2) << 2) attrs = {'width': 3} ExprTester(ctx, ctx.expr.bitvector_from_bool, inputs, attrs, output)
def test_cnf(): ctx = bitblaster.ExprContext(load_defaults=False) ctx.load_valtype('bitblaster.valtype.bool') ctx.load_expr_def_set('bitblaster.exprdefset.cnf') # Test we can create a boolean constant. v1 = ctx.variable(name='v1', valtype=ctx.valtype.bool()) v2 = ctx.variable(name='v2', valtype=ctx.valtype.bool()) # Create logical_or(v1, logical_not(v2)) expr = ctx.expr.logical_or(v1, ctx.expr.logical_not(v2)) # Add constraint. ctx.add_constraint(expr)
def test_duplicate_variable_name_in_ctx(): ctx = bitblaster.ExprContext(load_defaults=False) ctx.load_valtype('bitblaster.valtype.bool') bool1 = ctx.variable(name='bool1', valtype=ctx.valtype.bool()) # Check we can't use the same name twice. with pytest.raises( RuntimeError, match=r"variable with name 'bool1' already exists in context"): bool2 = ctx.variable(name='bool1', valtype=ctx.valtype.bool()) # Check we can use a different name. bool2 = ctx.variable(name='bool2', valtype=ctx.valtype.bool())
def test_solver_cnf(): ctx = bitblaster.ExprContext(load_defaults=False) ctx.load_expr_def_set('bitblaster.exprdefset.logical') a = ctx.variable(name="a", valtype=ctx.valtype.bool()) ctx.add_constraint(ctx.expr.logical_or(a)) result = ctx.util.solve() # Is satisfiable. assert(result) # Must have a=True varmap = result.get_varmap() assert(True == varmap[a])
def test_invalid_exprs(): ctx = bitblaster.ExprContext(load_defaults=False) ctx.load_valtype('bitblaster.valtype.bool') ctx.load_expr_def_set('bitblaster.exprdefset.cnf') # Test we can create a boolean constant. false = ctx.constant(value=True, valtype=ctx.valtype.bool()) v1 = ctx.variable(name='v1', valtype=ctx.valtype.bool()) # logical_or with constant. with pytest.raises( RuntimeError, match= r"'bitblaster.exprdefset.cnf.logical_or' operands must be either a boolean variable or a logical negation of a boolean variable \(operand 0 is '1'\)" ): ctx.expr.logical_or(false) # logical_or with logical_or. with pytest.raises( RuntimeError, match= r"'bitblaster.exprdefset.cnf.logical_or' operands must be either a boolean variable or a logical negation of a boolean variable \(operand 0 is 'logical_or\(v1\)'\)" ): ctx.expr.logical_or(ctx.expr.logical_or(v1)) # logical_not with constant with pytest.raises( RuntimeError, match= r"'bitblaster.exprdefset.cnf.logical_not' operand must be a boolean variable \(operand is '1'\)" ): ctx.expr.logical_not(false) # logical_not with logical_or with pytest.raises( RuntimeError, match= r"'bitblaster.exprdefset.cnf.logical_not' operand must be a boolean variable \(operand is 'logical_or\(v1\)'\)" ): ctx.expr.logical_not(ctx.expr.logical_or(v1)) # logical_not with logical_not with pytest.raises( RuntimeError, match= r"'bitblaster.exprdefset.cnf.logical_not' operand must be a boolean variable \(operand is 'logical_not\(v1\)'\)" ): ctx.expr.logical_not(ctx.expr.logical_not(v1))
def test_sat4(): ctx = bitblaster.ExprContext(load_defaults=False) ctx.load_expr_def_set('bitblaster.exprdefset.logical')# a = ctx.variable(name="a", valtype=ctx.valtype.bool()) b = ctx.variable(name="b", valtype=ctx.valtype.bool()) tt = ctx.constant(value=1, valtype=ctx.valtype.bool()) ff = ctx.constant(value=0, valtype=ctx.valtype.bool()) ctx.add_constraint(ctx.expr.logical_xnor(a, tt)) ctx.add_constraint(ctx.expr.logical_implies(a, b)) ctx.add_constraint(ctx.expr.logical_xnor(b, ff)) result = ctx.util.solve() # Is not satisfiable. assert(not result)
def test_logical_nand(): ctx = bitblaster.ExprContext() # Test with one input. inputs = [ctx.valtype.bool()] output = lambda op0: not op0 ExprTester(ctx, ctx.expr.logical_nand, inputs, {}, output) # Test with two inputs. inputs = [ctx.valtype.bool(), ctx.valtype.bool()] output = lambda op0, op1: not (op0 and op1) ExprTester(ctx, ctx.expr.logical_nand, inputs, {}, output) # Test with three inputs. inputs = [ctx.valtype.bool(), ctx.valtype.bool(), ctx.valtype.bool()] output = lambda op0, op1, op2: not (op0 and op1 and op2) ExprTester(ctx, ctx.expr.logical_nand, inputs, {}, output)
def test_constant(): ctx = bitblaster.ExprContext(load_defaults=False) ctx.load_valtype('bitblaster.valtype.bool') # Test we can create a boolean constant. bool1 = ctx.constant(value=True, valtype=ctx.valtype.bool()) bool2 = ctx.constant(value=False, valtype=ctx.valtype.bool()) # Check we can also create them with 0, 1. bool3 = ctx.constant(value=1, valtype=ctx.valtype.bool()) bool4 = ctx.constant(value=0, valtype=ctx.valtype.bool()) # Check object equivalences. assert (id(bool1) != id(bool2)) assert (id(bool1) == id(bool3)) assert (id(bool1) != id(bool4)) assert (id(bool2) == id(bool4))
def test_logical_or(): ctx = bitblaster.ExprContext() # Test with one input. inputs = [ctx.valtype.bool()] output = lambda op0: op0 ExprTester(ctx, ctx.expr.logical_or, inputs, {}, output) # Test with two inputs. inputs = [ctx.valtype.bool(), ctx.valtype.bool()] output = lambda op0, op1: op0 or op1 ExprTester(ctx, ctx.expr.logical_or, inputs, {}, output) # Test with three inputs. inputs = [ctx.valtype.bool(), ctx.valtype.bool(), ctx.valtype.bool()] output = lambda op0, op1, op2: op0 or op1 or op2 ExprTester(ctx, ctx.expr.logical_or, inputs, {}, output)
def test_logical_not(): ctx = bitblaster.ExprContext() v1 = ctx.variable(name='v1', valtype=ctx.valtype.bool()) true = ctx.constant(value=1, valtype=ctx.valtype.bool()) false = ctx.constant(value=0, valtype=ctx.valtype.bool()) # Can't simplify variable op. expr = ctx.expr.logical_not(v1) assert (ctx.util.simplify(expr) == expr) # logical_not(true) => false expr = ctx.expr.logical_not(true) assert (ctx.util.simplify(expr) == false) # logical_not(false) => true expr = ctx.expr.logical_not(false) assert (ctx.util.simplify(expr) == true) # logical_not(logical_not(v1)) => v1 expr = ctx.expr.logical_not(ctx.expr.logical_not(v1)) assert (ctx.util.simplify(expr) == v1)
def test_load(): ctx = bitblaster.ExprContext(load_defaults=False) ctx.load_valtype('bitblaster.valtype.bool') # Test we can create a boolean valtype. bool1 = ctx.valtype.bool() # Test that the context agrees it's a bool. assert (ctx.valtype.is_bool(bool1)) # Test it's equal to itself. assert (bool1 == bool1) # Test it's not not unequal to itself. assert (not (bool1 != bool1)) # Test calling with non-Valtype objects results in exception. with pytest.raises( RuntimeError, match= r"'is_bool' argument \('1'\) is not a bitblaster.Valtype object"): assert (not ctx.valtype.is_bool(1)) with pytest.raises( RuntimeError, match= r"'is_bool' argument \('False'\) is not a bitblaster.Valtype object" ): assert (not ctx.valtype.is_bool(False)) # Test if we create another bool it's the same object. bool2 = ctx.valtype.bool() assert (id(bool1) == id(bool2)) # Test __str__ and __repr__. assert ("bool" == str(bool1)) assert ("bool" == repr(bool1)) # Test values. assert (list(bool1.values()) == [False, True])
def test_variable(): ctx = bitblaster.ExprContext(load_defaults=False) ctx.load_valtype('bitblaster.valtype.bool') # Test we can create a boolean variable. bool1 = ctx.variable(name='bool1', valtype=ctx.valtype.bool())