def test_forall():
    a = A()

    sc = timewinder.statetree.StateController(timewinder.statetree.MemoryCAS())
    sc.mount("a", a)

    ok = timewinder.ForAll(A, lambda m: m.foo == "a")
    assert ok.check(sc)

    fail = timewinder.ForAll(A, lambda m: m.foo == "b")
    assert not fail.check(sc)
def test_check_and_withdraw_reinterp(benchmark):
    @timewinder.process
    def check_and_withdraw(sender, reciever, amt):
        if amt <= sender.acc:
            sender.acc = sender.acc - amt
            yield "deposit"
            reciever.acc = reciever.acc + amt

    no_overdrafts = timewinder.ForAll(Account, lambda a: a.acc >= 0)

    def reset_and_eval():
        alice = Account("alice", 5)
        bob = Account("bob", 5)

        ev = timewinder.Evaluator(
            objects=[alice, bob],
            threads=[
                check_and_withdraw(alice, bob, Set(range(1, 6))),
                check_and_withdraw(alice, bob, Set(range(1, 6))),
            ],
            specs=[no_overdrafts],
        )
        ev.evaluate(steps=10)
        return ev.stats

    stats = benchmark(reset_and_eval)

    assert stats.states == 225
Example #3
0
def test_overdraft_1():
    @timewinder.object
    class Account:
        def __init__(self, name):
            self.name = name
            self.acc = 5

    alice = Account("alice")
    bob = Account("bob")

    @timewinder.step
    def withdraw(state, sender, amount):
        sender.acc = sender.acc - amount

    @timewinder.step
    def deposit(state, reciever, amount):
        reciever.acc = reciever.acc + amount

    alg = timewinder.FuncProcess(
        withdraw(alice, 3),
        deposit(bob, 3),
    )

    no_overdrafts = timewinder.ForAll(Account, lambda a: a.acc >= 0)

    ev = timewinder.Evaluator(
        objects=[alice, bob],
        threads=[alg],
        specs=[no_overdrafts],
    )
    ev.evaluate()
    ev._print_state_space()
    assert ev.stats.states == 3
def test_overdraft_initial_conditions():
    alice = Account("alice", 5)
    bob = Account("bob", 5)

    @timewinder.process
    def withdraw(sender, reciever, amount):
        sender.acc = sender.acc - amount
        yield "deposit"
        reciever.acc = reciever.acc + amount

    no_overdrafts = timewinder.ForAll(Account, lambda a: a.acc >= 0)

    ev = timewinder.Evaluator(
        objects=[alice, bob],
        threads=[withdraw(alice, bob, Set(range(1, 7)))],
        specs=[no_overdrafts],
    )

    got_error = False
    try:
        ev.evaluate()
    except ConstraintError as e:
        got_error = True
        print(e.name)
        print(e.thunk)

    assert got_error
    assert ev.stats.states == 12
Example #5
0
def test_multiple_processes_if():
    @timewinder.object
    class Account:
        def __init__(self, name):
            self.name = name
            self.acc = 5

    alice = Account("alice")
    bob = Account("bob")

    @timewinder.step
    def withdraw(state, sender):
        sender.acc = sender.acc - state["amt"]

    @timewinder.step
    def deposit(state, reciever):
        reciever.acc = reciever.acc + state["amt"]

    @timewinder.step
    def check_funds(state, sender):
        if state["amt"] > sender.acc:
            raise timewinder.StopProcess()

    def alg():
        return timewinder.FuncProcess(
            check_funds(alice),
            withdraw(alice),
            deposit(bob),
            state={"amt": Set(range(1, 6))},
        )

    no_overdrafts = timewinder.ForAll(Account, lambda a: a.acc >= 0)

    ev = timewinder.Evaluator(
        objects=[alice, bob],
        threads=[alg(), alg()],
        specs=[no_overdrafts],
    )

    got_error = False
    try:
        ev.evaluate(steps=10)
    except ConstraintError as e:
        got_error = True
        print(e.name, " failed")
        ev.replay_thunk(e.thunk)

    assert got_error
    assert ev.stats.states == 295
Example #6
0
def test_overdraft_initial_conditions():
    @timewinder.object
    class Account:
        def __init__(self, name):
            self.name = name
            self.acc = 5

    alice = Account("alice")
    bob = Account("bob")

    @timewinder.step
    def withdraw(state, sender):
        sender.acc = sender.acc - state["amt"]

    @timewinder.step
    def deposit(state, reciever):
        reciever.acc = reciever.acc + state["amt"]

    alg = timewinder.FuncProcess(
        withdraw(alice),
        deposit(bob),
        state={
            "amt": Set(range(1, 7)),
        },
    )

    no_overdrafts = timewinder.ForAll(Account, lambda a: a.acc >= 0)

    ev = timewinder.Evaluator(
        objects=[alice, bob],
        threads=[alg],
        specs=[no_overdrafts],
    )

    got_error = False
    try:
        ev.evaluate()
    except ConstraintError as e:
        got_error = True
        print(e.name)
        print(e.thunk)

    assert got_error
    assert ev.stats.states == 12
def bounded_queue_example(n_producers, n_consumers, queue_size):
    n_threads = n_producers + n_consumers
    runnable = CondWait(n_producers, n_consumers)
    bqueue = BoundedQueue(queue_size)

    threads = []
    for i in range(n_threads):
        if i < n_producers:
            threads.append(producer(bqueue, runnable, i))
        else:
            threads.append(consumer(bqueue, runnable, i))

    no_deadlocks = timewinder.ForAll(CondWait, lambda c: any(c.status))

    return timewinder.Evaluator(
        objects=[runnable, bqueue],
        specs=[no_deadlocks],
        threads=threads,
    )
def test_liveness_reinterp():
    @timewinder.process
    def check_and_withdraw(sender, reciever, amt):
        if amt <= sender.acc:
            sender.acc = sender.acc - amt
            yield "deposit"
            reciever.acc = reciever.acc + amt

    no_overdrafts = timewinder.ForAll(Account, lambda a: a.acc >= 0)

    @timewinder.predicate
    def consistent_total(a, b):
        total = a.acc + b.acc
        return total == 10

    alice = Account("alice", 5)
    bob = Account("bob", 5)

    eventually_consistent = timewinder.Eventually(
        timewinder.Always(consistent_total(alice, bob)))

    ev = timewinder.Evaluator(
        objects=[alice, bob],
        threads=[
            check_and_withdraw(alice, bob, Set(range(1, 6))),
            check_and_withdraw(alice, bob, Set(range(1, 6))),
        ],
        specs=[
            no_overdrafts,
            eventually_consistent,
        ],
    )

    got_error = False
    try:
        ev.evaluate(steps=10)
    except StutterConstraintError as s:
        got_error = True
        print("\n" + s.name + "\n")
        ev.replay_thunk(s.thunk)

    assert got_error
Example #9
0
def test_check_and_withdraw(benchmark):
    @timewinder.object
    class Account:
        def __init__(self, name):
            self.name = name
            self.acc = 5

    @timewinder.step
    def deposit(state, reciever):
        reciever.acc = reciever.acc + state["amt"]

    @timewinder.step
    def check_and_withdraw(state, sender):
        if state["amt"] > sender.acc:
            raise timewinder.StopProcess()
        else:
            sender.acc = sender.acc - state["amt"]

    no_overdrafts = timewinder.ForAll(Account, lambda a: a.acc >= 0)

    def reset_and_eval():
        alice = Account("alice")
        bob = Account("bob")

        def alg():
            return timewinder.FuncProcess(
                check_and_withdraw(alice),
                deposit(bob),
                state={"amt": Set(range(1, 6))},
            )

        ev = timewinder.Evaluator(
            objects=[alice, bob],
            threads=[alg(), alg()],
            specs=[no_overdrafts],
        )
        ev.evaluate(steps=10)
        return ev.stats

    stats = benchmark(reset_and_eval)

    assert stats.states == 225
def test_overdraft_1():
    alice = Account("alice", 5)
    bob = Account("bob", 5)

    @timewinder.process
    def withdraw(sender, reciever, amount):
        sender.acc = sender.acc - amount
        yield "deposit"
        reciever.acc = reciever.acc + amount

    no_overdrafts = timewinder.ForAll(Account, lambda a: a.acc >= 0)

    ev = timewinder.Evaluator(
        objects=[alice, bob],
        threads=[withdraw(alice, bob, 3)],
        specs=[no_overdrafts],
    )
    ev.evaluate()
    ev._print_state_space()
    assert ev.stats.states == 3
@timewinder.process
def check_and_withdraw(sender, reciever, amt):
    if amt <= sender.acc:
        sender.acc = sender.acc - amt
        yield "deposit"
        reciever.acc = reciever.acc + amt


# Instantiate our example account objects
alice = Account("alice", 5)
bob = Account("bob", 5)


# Create a predicate that says, at every stage, all Account
# objects must carry positive balances.
no_overdrafts = timewinder.ForAll(Account, lambda a: a.acc >= 0)


# Run the evaluator.
ev = timewinder.Evaluator(
    # Pass our two objects
    objects=[alice, bob],
    # Declare the predicates we want to check.
    specs=[no_overdrafts],
    # Only have one thread do a withdrawal of too much
    # money, and it should fail.
    #
    threads=[withdraw(alice, bob, 6)],
    # Alternately, run two threads, both withdrawing from Alice and depositing
    # to Bob's account. The `Set` function is a generator that will
    # try every transfer amount from 1 to 5, as per Python's `range`
Example #12
0

THREADS = PRODUCERS + CONSUMERS
runnable = CondWait(PRODUCERS, CONSUMERS)
bqueue = BoundedQueue(QUEUE_SIZE)


threads = []
for i in range(THREADS):
    if i < PRODUCERS:
        threads.append(producer(bqueue, runnable, i))
    else:
        threads.append(consumer(bqueue, runnable, i))


no_deadlocks = timewinder.ForAll(CondWait, lambda c: any(c.status))


ev = timewinder.Evaluator(
    objects=[runnable, bqueue],
    specs=[no_deadlocks],
    threads=threads,
)


err = None
try:
    ev.evaluate(steps=None)
except timewinder.ConstraintError as e:
    err = e