Beispiel #1
0
def test_unregister_after_interrupt(env):
    """If a process is interrupted while waiting for another one, it
    should be unregistered from that process.

    """
    def interruptor(env, process):
        yield env.timeout(1)
        process.interrupt()

    def child(env):
        yield env.timeout(2)

    def parent(env):
        child_proc = env.start(child(env))
        try:
            yield child_proc
            pytest.fail('Did not receive an interrupt.')
        except Interrupt:
            assert env.now == 1
            assert child_proc.is_alive

        yield env.timeout(2)
        assert env.now == 3
        assert not child_proc.is_alive

    parent_proc = env.start(parent(env))
    env.start(interruptor(env, parent_proc))
    simulate(env)
Beispiel #2
0
def test_interrupted_join(env):
    """Tests that interrupts are raised while the victim is waiting for
    another process. The victim should get unregistered from the other
    process.

    """
    def interruptor(env, process):
        yield env.timeout(1)
        process.interrupt()

    def child(env):
        yield env.timeout(2)

    def parent(env):
        child_proc = env.start(child(env))
        try:
            yield child_proc
            pytest.fail('Did not receive an interrupt.')
        except Interrupt:
            assert env.now == 1
            assert child_proc.is_alive

            # We should not get resumed when child terminates.
            yield env.timeout(5)
            assert env.now == 6

    parent_proc = env.start(parent(env))
    env.start(interruptor(env, parent_proc))
    simulate(env)
Beispiel #3
0
def test_wait_for_all_with_errors(env):
    """On default wait_for_all should fail immediately if one of its events
    fails."""
    def child_with_error(env, value):
        yield env.timeout(value)
        raise RuntimeError('crashing')

    def parent(env):
        events = [
            env.timeout(1, value=1),
            env.start(child_with_error(env, 2)),
            env.timeout(3, value=3)
        ]

        try:
            condition = all_of(events)
            yield condition
            assert False, 'There should have been an exception'
        except RuntimeError as e:
            assert e.args[0] == 'crashing'

        # Although the condition has failed, intermediate results are
        # available.
        assert condition._results[events[0]] == 1
        assert condition._results[events[1]].args[0] == 'crashing'
        # The last child has not terminated yet.
        assert events[2] not in condition._results

    env.start(parent(env))
    simulate(env)
Beispiel #4
0
def test_blackbox_monitor_processes(env):
    """A :class:`~simpy.monitoring.Monitor` also provides a process
    method (:meth:`Monitor.run()`) that collects data from a number of
    objects in regular intervals.

    """
    class Spam(object):
        def __init__(self, env):
            self.a = 0
            self.process = env.start(self.pem(env))

        def pem(self, env):
            while True:
                self.a += env.now
                yield env.timeout(1)

    spams = [Spam(env) for i in range(2)]
    monitor = monitoring.Monitor()

    # configure also accepts a generator that creates a number of
    # collector functions:
    monitor.configure(lambda: [env.now] + [spam.a for spam in spams])
    env.start(monitor.run(env, collect_interval=1))

    simpy.simulate(env, 3)
    assert monitor.data == [
        # (env.now, spam[0].a, spam[1].a)
        [0, 0, 0],
        [1, 1, 1],
        [2, 3, 3],
    ]
Beispiel #5
0
def test_resource_release_after_interrupt(env):
    """A process needs to release a resource, even it it was interrupted
    and does not continue to wait for it."""
    def pem(env, res):
        with res.request() as req:
            yield req
            yield env.timeout(1)

    def victim(env, res):
        try:
            evt = res.request()
            yield evt
            pytest.fail('Should not have gotten the resource.')
        except simpy.Interrupt:
            # Dont wait for the resource
            res.release(evt)
            assert env.now == 0
            env.exit()

    def interruptor(env, proc):
        proc.interrupt()
        yield env.exit(0)

    res = simpy.Resource(env, 1)
    victim_proc = env.start(victim(env, res))
    env.start(interruptor(env, victim_proc))
    env.start(pem(env, res))
    simpy.simulate(env)
Beispiel #6
0
def test_resource_continue_after_interrupt(env):
    """A process may be interrupted while waiting for a resource but
    should be able to continue waiting afterwards."""
    def pem(env, res):
        with res.request() as req:
            yield req
            yield env.timeout(1)

    def victim(env, res):
        try:
            evt = res.request()
            yield evt
            pytest.fail('Should not have gotten the resource.')
        except simpy.Interrupt:
            yield evt
            res.release(evt)
            assert env.now == 1

    def interruptor(env, proc):
        proc.interrupt()
        yield env.exit(0)

    res = simpy.Resource(env, 1)
    env.start(pem(env, res))
    proc = env.start(victim(env, res))
    env.start(interruptor(env, proc))
    simpy.simulate(env)
Beispiel #7
0
def test_container(env, log):
    """A *container* is a resource (of optinally limited capacity) where
    you can put in our take out a discrete or continuous amount of
    things (e.g., a box of lump sugar or a can of milk).  The *put* and
    *get* operations block if the buffer is to full or to empty. If they
    return, the process nows that the *put* or *get* operation was
    successfull.

    """
    def putter(env, buf, log):
        yield env.timeout(1)
        while True:
            yield buf.put(2)
            log.append(('p', env.now))
            yield env.timeout(1)

    def getter(env, buf, log):
        yield buf.get(1)
        log.append(('g', env.now))

        yield env.timeout(1)
        yield buf.get(1)
        log.append(('g', env.now))

    buf = simpy.Container(env, init=0, capacity=2)
    env.start(putter(env, buf, log))
    env.start(getter(env, buf, log))
    simpy.simulate(env, until=5)

    assert log == [('g', 1), ('p', 1), ('g', 2), ('p', 2)]
Beispiel #8
0
def test_whitebox_monitor_data_object(env):
    """If the *PEM* is an instance method of an object,
    a :class:`~simpy.monitoring.Monitor` can be configured to
    automatically collect a nummber of instance attributes.

    """

    class Spam(object):
        def __init__(self, env):
            self.env = env
            self.a = 0
            self.monitor = monitoring.Monitor()
            self.monitor.configure(lambda: (self.env.now, self.a))
            self.process = env.start(self.pem())

        def pem(self):
            while True:
                self.a += self.env.now
                self.monitor.collect()
                yield self.env.timeout(1)

    spam = Spam(env)  # Spam.__init__ starts the PEM
    simpy.simulate(env, 5)

    assert spam.monitor.data == [(0, 0), (1, 1), (2, 3), (3, 6), (4, 10)]
Beispiel #9
0
def test_start_delayed(env):
    def pem(env):
        assert env.now == 5
        yield env.timeout(1)

    start_delayed(env, pem(env), delay=5)
    simulate(env)
Beispiel #10
0
def test_exception_chaining(env):
    """Unhandled exceptions pass through the entire event stack. This must be
    visible in the stacktrace of the exception."""
    def child(env):
        yield env.timeout(1)
        raise RuntimeError('foo')

    def parent(env):
        child_proc = env.start(child(env))
        yield child_proc

    def grandparent(env):
        parent_proc = env.start(parent(env))
        yield parent_proc

    env.start(grandparent(env))
    try:
        simpy.simulate(env)
        pytest.fail('There should have been an exception')
    except RuntimeError:
        import traceback
        trace = traceback.format_exc()
        assert 'raise RuntimeError(\'foo\')' in trace
        assert 'yield child_proc' in trace
        assert 'yield parent_proc' in trace
Beispiel #11
0
def test_resource_release_after_interrupt(env):
    """A process needs to release a resource, even it it was interrupted
    and does not continue to wait for it."""
    def pem(env, res):
        with res.request() as req:
            yield req
            yield env.timeout(1)

    def victim(env, res):
        try:
            evt = res.request()
            yield evt
            pytest.fail('Should not have gotten the resource.')
        except simpy.Interrupt:
            # Dont wait for the resource
            res.release(evt)
            assert env.now == 0
            env.exit()

    def interruptor(env, proc):
        proc.interrupt()
        yield env.exit(0)

    res = simpy.Resource(env, 1)
    victim_proc = env.start(victim(env, res))
    env.start(interruptor(env, victim_proc))
    env.start(pem(env, res))
    simpy.simulate(env)
Beispiel #12
0
def test_blackbox_monitor_processes(env):
    """A :class:`~simpy.monitoring.Monitor` also provides a process
    method (:meth:`Monitor.run()`) that collects data from a number of
    objects in regular intervals.

    """

    class Spam(object):
        def __init__(self, env):
            self.a = 0
            self.process = env.start(self.pem(env))

        def pem(self, env):
            while True:
                self.a += env.now
                yield env.timeout(1)

    spams = [Spam(env) for i in range(2)]
    monitor = monitoring.Monitor()

    # configure also accepts a generator that creates a number of
    # collector functions:
    monitor.configure(lambda: [env.now] + [spam.a for spam in spams])
    env.start(monitor.run(env, collect_interval=1))

    simpy.simulate(env, 3)
    assert monitor.data == [
        # (env.now, spam[0].a, spam[1].a)
        [0, 0, 0],
        [1, 1, 1],
        [2, 3, 3],
    ]
Beispiel #13
0
def test_mixed_preemption(env, log):
    def process(id, env, res, delay, prio, preempt, log):
        yield env.timeout(delay)
        with res.request(priority=prio, preempt=preempt) as req:
            try:
                yield req
                yield env.timeout(5)
                log.append((env.now, id))
            except simpy.Interrupt as ir:
                log.append((env.now, id, tuple(ir.cause)))

    res = simpy.PreemptiveResource(env, 2)
    p0 = env.start(process(0, env, res, 0, 1, True, log))
    p1 = env.start(process(1, env, res, 0, 1, True, log))
    p2 = env.start(process(2, env, res, 1, 0, False, log))
    p3 = env.start(process(3, env, res, 1, 0, True, log))
    p4 = env.start(process(4, env, res, 2, 2, True, log))

    simpy.simulate(env)

    assert log == [
        (1, 1, (p3, 0)),
        (5, 0),
        (6, 3),
        (10, 2),
        (11, 4),
    ]
Beispiel #14
0
def test_interrupted_join_and_rejoin(env):
    """Tests that interrupts are raised while the victim is waiting for
    another process. The victim tries to join again.

    """
    def interruptor(env, process):
        yield env.timeout(1)
        process.interrupt()

    def child(env):
        yield env.timeout(2)

    def parent(env):
        child_proc = env.start(child(env))
        try:
            yield child_proc
            pytest.fail('Did not receive an interrupt.')
        except Interrupt:
            assert env.now == 1
            assert child_proc.is_alive

            yield child_proc
            assert env.now == 2

    parent_proc = env.start(parent(env))
    env.start(interruptor(env, parent_proc))
    simulate(env)
Beispiel #15
0
def test_wait_for_all_with_errors(env):
    """On default wait_for_all should fail immediately if one of its events
    fails."""
    def child_with_error(env, value):
        yield env.timeout(value)
        raise RuntimeError('crashing')

    def parent(env):
        events = [env.timeout(1, value=1),
            env.start(child_with_error(env, 2)),
            env.timeout(3, value=3)]

        try:
            condition = all_of(events)
            yield condition
            assert False, 'There should have been an exception'
        except RuntimeError as e:
            assert e.args[0] == 'crashing'

        # Although the condition has failed, intermediate results are
        # available.
        assert condition._results[events[0]] == 1
        assert condition._results[events[1]].args[0] == 'crashing'
        # The last child has not terminated yet.
        assert events[2] not in condition._results

    env.start(parent(env))
    simulate(env)
Beispiel #16
0
def test_resource_monitor(env, res_mon):
    def pem(env, resource, wait, use):
        yield env.timeout(wait)
        with resource.request() as req:
            yield req
            yield env.timeout(use)

    resource = simpy.Resource(env, 2)
    monitor = res_mon(resource)
    env.start(pem(env, resource, 0, 1))
    env.start(pem(env, resource, 0, 2))
    env.start(pem(env, resource, 0, 1))
    env.start(pem(env, resource, 3, 3))
    env.start(pem(env, resource, 3, 1))
    env.start(pem(env, resource, 4, 1))
    simpy.simulate(env)
    monitor.collect()

    # Convert the data and replace the ID-lists with their length.
    monitor._backend.data = [(t, len(u), len(g)) for t, u, g in monitor.data]

    assert monitor.data == [
        (0, 0, 0), (0, 1, 0), (0, 2, 0),
        (1, 2, 1),
        (2, 2, 0), (2, 1, 0),
        (3, 0, 0), (3, 1, 0),
        (4, 2, 0), (4, 2, 1),
        (5, 2, 0),
        (6, 1, 0),
        (6, 0, 0),
    ]
Beispiel #17
0
def test_start_delayed(env):
    def pem(env):
        assert env.now == 5
        yield env.timeout(1)

    start_delayed(env, pem(env), delay=5)
    simulate(env)
Beispiel #18
0
def test_resource_continue_after_interrupt(env):
    """A process may be interrupted while waiting for a resource but
    should be able to continue waiting afterwards."""
    def pem(env, res):
        with res.request() as req:
            yield req
            yield env.timeout(1)

    def victim(env, res):
        try:
            evt = res.request()
            yield evt
            pytest.fail('Should not have gotten the resource.')
        except simpy.Interrupt:
            yield evt
            res.release(evt)
            assert env.now == 1

    def interruptor(env, proc):
        proc.interrupt()
        yield env.exit(0)

    res = simpy.Resource(env, 1)
    env.start(pem(env, res))
    proc = env.start(victim(env, res))
    env.start(interruptor(env, proc))
    simpy.simulate(env)
Beispiel #19
0
def test_container(env, log):
    """A *container* is a resource (of optinally limited capacity) where
    you can put in our take out a discrete or continuous amount of
    things (e.g., a box of lump sugar or a can of milk).  The *put* and
    *get* operations block if the buffer is to full or to empty. If they
    return, the process nows that the *put* or *get* operation was
    successfull.

    """
    def putter(env, buf, log):
        yield env.timeout(1)
        while True:
            yield buf.put(2)
            log.append(('p', env.now))
            yield env.timeout(1)

    def getter(env, buf, log):
        yield buf.get(1)
        log.append(('g', env.now))

        yield env.timeout(1)
        yield buf.get(1)
        log.append(('g', env.now))

    buf = simpy.Container(env, init=0, capacity=2)
    env.start(putter(env, buf, log))
    env.start(getter(env, buf, log))
    simpy.simulate(env, until=5)

    assert log == [('g', 1), ('p', 1), ('g', 2), ('p', 2)]
Beispiel #20
0
def test_mixed_preemption(env, log):
    def process(id, env, res, delay, prio, preempt, log):
        yield env.timeout(delay)
        with res.request(priority=prio, preempt=preempt) as req:
            try:
                yield req
                yield env.timeout(5)
                log.append((env.now, id))
            except simpy.Interrupt as ir:
                log.append((env.now, id, tuple(ir.cause)))

    res = simpy.PreemptiveResource(env, 2)
    p0 = env.start(process(0, env, res, 0, 1, True, log))
    p1 = env.start(process(1, env, res, 0, 1, True, log))
    p2 = env.start(process(2, env, res, 1, 0, False, log))
    p3 = env.start(process(3, env, res, 1, 0, True, log))
    p4 = env.start(process(4, env, res, 2, 2, True, log))

    simpy.simulate(env)

    assert log == [
        (1, 1, (p3, 0)),
        (5, 0),
        (6, 3),
        (10, 2),
        (11, 4),
    ]
Beispiel #21
0
def test_interrupt_self(env):
    """A processs should not be able to interrupt itself."""
    def pem(env):
        pytest.raises(RuntimeError, env.active_process.interrupt)
        yield env.timeout(0)

    env.start(pem(env))
    simpy.simulate(env)
Beispiel #22
0
def test_resource_with_condition(env):
    def process(env, resource):
        with resource.request() as res_event:
            result = yield res_event | env.timeout(1)
            assert res_event in result

    resource = simpy.Resource(env, 1)
    env.start(process(env, resource))
    simpy.simulate(env)
Beispiel #23
0
def test_resource_with_condition(env):
    def process(env, resource):
        with resource.request() as res_event:
            result = yield res_event | env.timeout(1)
            assert res_event in result

    resource = simpy.Resource(env, 1)
    env.start(process(env, resource))
    simpy.simulate(env)
Beispiel #24
0
def test_operator_or(env):
    def process(env):
        timeout = [env.timeout(delay, value=delay) for delay in range(3)]
        results = yield timeout[0] | timeout[1] | timeout[2]

        assert results == {
            timeout[0]: 0,
        }

    env.start(process(env))
    simulate(env)
Beispiel #25
0
def test_exception_handling(env):
    """If failed events are not defused (which is the default) the simulation
    crashes."""

    event = env.event()
    event.fail(RuntimeError())
    try:
        simpy.simulate(env, until=1)
        assert False, 'There must be a RuntimeError!'
    except RuntimeError as e:
        pass
def test_exit_with_process(env):
    def child(env, fork):
        yield env.exit(env.start(child(env, False)) if fork else None)

    def parent(env):
        result = yield env.start(child(env, True))

        assert type(result) is Process

    env.start(parent(env))
    simulate(env)
def test_discrete_time_steps(env, log):
    """envple envulation with discrete time steps."""
    def pem(env, log):
        while True:
            log.append(env.now)
            yield env.timeout(delay=1)

    env.start(pem(env, log))
    simulate(env, until=3)

    assert log == [0, 1, 2]
def test_shared_timeout(env, log):
    def child(env, timeout, id, log):
        yield timeout
        log.append((id, env.now))

    timeout = env.timeout(1)
    for i in range(3):
        env.start(child(env, timeout, i, log))

    simulate(env)
    assert log == [(0, 1), (1, 1), (2, 1)]
def test_stop_self(env, log):
    """Process stops itself."""
    def pem(env, log):
        while env.now < 2:
            log.append(env.now)
            yield env.timeout(1)

    env.start(pem(env, log))
    simulate(env, 10)

    assert log == [0, 1]
Beispiel #30
0
def test_operator_or(env):
    def process(env):
        timeout = [env.timeout(delay, value=delay) for delay in range(3)]
        results = yield timeout[0] | timeout[1] | timeout[2]

        assert results == {
                timeout[0]: 0,
        }

    env.start(process(env))
    simulate(env)
Beispiel #31
0
def test_any_of(env):
    """Wait for any event to be triggered."""
    def parent(env):
        # Start 10 events.
        events = [env.timeout(i, value=i) for i in range(10)]
        results = yield any_of(events)

        assert results == {events[0]: 0}
        assert env.now == 0

    env.start(parent(env))
    simulate(env)
Beispiel #32
0
def test_any_of(env):
    """Wait for any event to be triggered."""
    def parent(env):
        # Start 10 events.
        events = [env.timeout(i, value=i) for i in range(10)]
        results = yield any_of(events)

        assert results == {events[0]: 0}
        assert env.now == 0

    env.start(parent(env))
    simulate(env)
Beispiel #33
0
def test_invalid_event(env):
    """Invalid yield values will cause the simulation to fail."""

    def root(env):
        yield None

    env.start(root(env))
    try:
        simpy.simulate(env)
        pytest.fail('Hey, this is not allowed!')
    except RuntimeError as err:
        assert err.args[0].endswith('Invalid yield value "None"')
Beispiel #34
0
def test_callback_exception_handling(env):
    """Callbacks of events may handle exception by setting the ``defused``
    attribute of ``event`` to ``True``."""
    def callback(event, type, value):
        event.defused = True

    event = env.event()
    event.callbacks.append(callback)
    event.fail(RuntimeError())
    assert not hasattr(event, 'defused'), 'Event has been defused immediately'
    simpy.simulate(env, until=1)
    assert event.defused, 'Event has not been defused'
Beispiel #35
0
def test_wait_for_proc(env):
    """A process can wait until another process finishes."""
    def finisher(env):
        yield env.timeout(5)

    def waiter(env, finisher):
        proc = env.start(finisher(env))
        yield proc  # Waits until "proc" finishes

        assert env.now == 5

    env.start(waiter(env, finisher))
    simulate(env)
Beispiel #36
0
def test_ior_with_and_cond(env):
    def process(env):
        cond = env.timeout(1, value=1) & env.timeout(2, value=2)
        orig = cond

        cond |= env.timeout(0, value=0)
        assert cond is not orig

        results = yield cond
        assert sorted(results.values()) == [0]

    env.start(process(env))
    simulate(env)
Beispiel #37
0
def test_operator_nested_and(env):
    def process(env):
        timeout = [env.timeout(delay, value=delay) for delay in range(3)]
        results = yield (timeout[0] & timeout[2]) | timeout[1]

        assert results == {
            timeout[0]: 0,
            timeout[1]: 1,
        }
        assert env.now == 1

    env.start(process(env))
    simulate(env)
Beispiel #38
0
def test_subscribe_at_timeout(env):
    """You should be able to subscribe at arbitrary events."""
    def pem(env):
        to = env.timeout(2)
        subscribe_at(to)
        try:
            yield env.timeout(10)
        except Interrupt as interrupt:
            assert interrupt.cause == (to, None)
            assert env.now == 2

    env.start(pem(env))
    simulate(env)
Beispiel #39
0
def test_cond_with_nested_error(env):
    def explode(env, delay):
        yield env.timeout(delay)
        raise ValueError('Onoes, failed after %d!' % delay)

    def process(env):
        try:
            yield env.start(explode(env, 0)) & env.timeout(1) | env.timeout(1)
            pytest.fail('The condition should have raised a ValueError')
        except ValueError as err:
            assert err.args == ('Onoes, failed after 0!', )

    env.start(process(env))
    simulate(env)
Beispiel #40
0
def test_subscribe_at_timeout_with_value(env):
    """An event's value should be accessible via the interrupt cause."""
    def pem(env):
        val = 'ohai'
        to = env.timeout(2, value=val)
        subscribe_at(to)
        try:
            yield env.timeout(10)
        except Interrupt as interrupt:
            assert interrupt.cause == (to, val)
            assert env.now == 2

    env.start(pem(env))
    simulate(env)
Beispiel #41
0
def test_any_of_chaining(env):
    """If a any_of condition A is chained to a any_of condition B,
    B will be merged into A."""
    def parent(env):
        condition_A = any_of([env.timeout(i, value=i) for i in range(2)])
        condition_B = any_of([env.timeout(i, value=i) for i in range(2)])

        condition_A |= condition_B

        results = yield condition_A
        assert sorted(results.values()) == [0, 0]

    env.start(parent(env))
    simulate(env)
Beispiel #42
0
def test_any_of_with_triggered_events(env):
    """Only pending events may be added to a any_of condition."""
    def parent(env):
        event = env.timeout(1)
        yield env.timeout(2)

        try:
            any_of([event])
            assert False, 'Expected an exception'
        except RuntimeError as e:
            assert e.args[0] == 'Event Timeout(1) has already been triggered'

    env.start(parent(env))
    simulate(env)
def test_timeout_value(env):
    """You can pass an additional *value* to *timeout* which will be
    directly yielded back into the PEM. This is useful to implement some
    kinds of resources or other additions.

    See :class:`envpy.resources.Store` for an example.

    """
    def pem(env):
        val = yield env.timeout(1, 'ohai')
        assert val == 'ohai'

    env.start(pem(env))
    simulate(env)
Beispiel #44
0
def test_child_exception(env):
    """A child catches an exception and sends it to its parent."""
    def child(env):
        try:
            yield env.timeout(1)
            raise RuntimeError('Onoes!')
        except RuntimeError as err:
            env.exit(err)

    def parent(env):
        result = yield env.start(child(env))
        assert isinstance(result, Exception)

    env.start(parent(env))
    simulate(env)
Beispiel #45
0
def test_interrupt_event(env):
    """A process should be interruptable while waiting for an Event."""
    def child(env):
        try:
            yield env.event()
        except simpy.Interrupt:
            assert env.now == 5

    def parent(env):
        child_proc = env.start(child(env))
        yield env.timeout(5)
        child_proc.interrupt()

    env.start(parent(env))
    simpy.simulate(env)