Example #1
0
def test_processes():
    q = Queue()

    @timewinder.process
    def writer(q):
        while True:
            yield "Write"
            q.queue.append("msg")

    @timewinder.process
    def reader(q):
        while True:
            yield "Read"
            _ = q.queue[0]
            q.queue = q.queue[1:]

    ev = timewinder.Evaluator(
        objects=[q],
        threads=[writer(q), reader(q)],
        specs=[bounded_queue(q, 2)],
    )

    got_error = False
    try:
        ev.evaluate()
    except timewinder.ProcessException as e:
        got_error = True
        print(e)

    assert got_error
Example #2
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
Example #3
0
def test_emulate_await_p2():
    q = Queue()

    @timewinder.process
    def writer(q):
        while True:
            yield "Write"
            q.queue.append("msg")
            while len(q.queue) >= 2:
                yield "Waiting"

    @timewinder.process
    def reader(q):
        while True:
            yield "Read"
            if len(q.queue) == 0:
                continue
            _ = q.queue[0]
            q.queue = q.queue[1:]

    ev = timewinder.Evaluator(
        objects=[q],
        threads=[writer(q), reader(q)],
        specs=[bounded_queue(q, 2)],
    )

    try:
        ev.evaluate(steps=100)
    except timewinder.ConstraintError as e:
        print(e.name)
        ev.replay_thunk(e.thunk)
        assert False

    assert ev.stats.states == 13
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_emulate_await_p1():
    q = Queue()

    @timewinder.process
    def writer(q):
        while True:
            yield "Write"
            q.queue.append("msg")

    @timewinder.process
    def reader(q):
        while True:
            yield "Read"
            if len(q.queue) == 0:
                continue
            _ = q.queue[0]
            q.queue = q.queue[1:]

    ev = timewinder.Evaluator(
        objects=[q],
        threads=[writer(q), reader(q)],
        specs=[bounded_queue(q, 2)],
    )

    got_error = False
    try:
        ev.evaluate()
    except timewinder.ConstraintError as e:
        got_error = True
        assert e.name.find("bounded_queue") >= 0
        print(e.name)
        ev.replay_thunk(e.thunk)

    assert got_error
Example #6
0
def test_run_deep_calls():
    object = A()

    @timewinder.step
    def a(state, m):
        print("in a")
        m.foo = "b"

    @timewinder.step
    def b(state, m):
        m.foo = "c"

    @timewinder.step
    def c(state, m):
        m.foo = "end1"

    @timewinder.step
    def d(state, m):
        m.foo = "end2"

    alg = timewinder.FuncProcess(
        a(object),
        b(object),
        c(object),
        d(object),
    )

    ev = timewinder.Evaluator(
        objects=[object],
        threads=[alg],
    )

    ev.evaluate()
    assert ev.stats.states == 5
    ev._print_state_space()
    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
Example #8
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
def test_abi_thread_idx():
    @timewinder.object
    @dataclass
    class Result:
        result: int

    @timewinder.process
    def get_thread_id(res):
        res.result = ThreadID()

    r = Result(-1)

    ev = timewinder.Evaluator(
        objects=[r],
        threads=[get_thread_id(r)],
    )
    ev.evaluate()
    assert r.result == 0
Example #10
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
Example #11
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
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
Example #15
0
def test_transmit_extension():
    q = Queue(40)
    max_queue_length = 7

    @timewinder.process
    def writer(q, max):
        while q.to_transmit != 0:
            yield "Write"
            q.queue.append("msg")
            q.to_transmit -= 1
            while len(q.queue) >= max:
                yield "Waiting"

    @timewinder.process
    def reader(q):
        while q.to_transmit > 0 or len(q.queue) > 0:
            yield "Read"
            if len(q.queue) == 0:
                continue
            _ = q.queue[0]
            q.queue = q.queue[1:]

    ev = timewinder.Evaluator(
        objects=[q],
        threads=[writer(q, max_queue_length),
                 reader(q)],
        specs=[
            bounded_queue(q, max_queue_length),
        ],
    )

    try:
        ev.evaluate(steps=None)
    except timewinder.ConstraintError as e:
        print(e.name)
        ev.replay_thunk(e.thunk)
        raise e

    assert ev.stats.states == 555
Example #16
0

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


if err is None:
    print(ev.stats)
else:
    print(f"\nConstraint Violated: {err.name}\n")
# 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`
    # builtin.
    #
    # This should fail, as both must complete and will in some cases
    # (both amounts at 1) but will fail if too much is transferred.
    #
    # threads=[
    #    check_and_withdraw(alice, bob, Set(range(1, 6))),
    #    check_and_withdraw(alice, bob, Set(range(1, 6))),
    # ],
)

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