def test_queue_timeout(): result = 0 queue = Queue() sim = Simulator() def join_then_balk(): nonlocal result try: queue.join(10.0) result = -1 except Timeout: result = 1 sim.stop() def would_pop(): nonlocal result advance(20.0) queue.pop() result += 1 sim.add(join_then_balk) sim.add(would_pop) sim.run() assert result == 1 assert (sim.now() == pytest.approx(10.0)) assert len(queue) == 0 sim.run() assert result == 2 assert (sim.now() == pytest.approx(20.0))
def test_progress_capture(): log = [] def capture(progress_min, _rt_remaining, mc): log.append(progress_min) a = 0 b = 0 def set_ab(new_a, new_b): nonlocal a, b a = new_a b = new_b def measure(): return (a, b) sim = Simulator() sim.add(track_progress, measure, [10, 10], 10.0, capture) sim._schedule(15.0, set_ab, 2, 0) sim._schedule(25.0, set_ab, 4, 1) sim._schedule(35.0, set_ab, 4, 6) sim._schedule(45.0, set_ab, 5, 9) sim._schedule(55.0, set_ab, 10, 10) sim.run(100.0) assert sim.now() == pytest.approx(60.0) assert log == pytest.approx([0.0, 0.0, 0.1, 0.4, 0.5, 1.0])
def test_auto_log_resource_take_again(auto_logger): def process(res): local.name = "proc" res.take(2) advance(10) res.take(3) advance(10) res.release(5) sim = Simulator(name="sim") resource = Resource(5, name="res") sim.add(process, resource) sim.run() check_log( auto_logger, (logging.INFO, 0.0, "", "Simulator", "sim", "add", dict(fn=process, args=(resource, ), kwargs={})), (logging.INFO, 0.0, "", "Simulator", "sim", "run", dict(duration=inf)), (logging.INFO, 0.0, "proc", "Resource", "res", "take", dict(num_instances=2, free=5)), (logging.INFO, 0.0, "proc", "Process", "proc", "advance", dict(delay=10.0)), (logging.INFO, 10.0, "proc", "Resource", "res", "take", dict(num_instances=3, free=3)), (logging.WARNING, 10.0, "proc", "Resource", "res", "take-again", dict(already=2, more=3)), (logging.INFO, 10.0, "proc", "Process", "proc", "advance", dict(delay=10.0)), (logging.INFO, 20.0, "proc", "Resource", "res", "release", dict(num_instances=5, keeping=0, free=5)), (logging.INFO, 20.0, "proc", "Process", "proc", "die-finish", {}), (logging.INFO, 20.0, "", "Simulator", "sim", "stop", {}))
def test_auto_log_queue(auto_logger): def proc(q): local.name = "the-process" q.join() advance(100) sim = Simulator() queue = Queue(name="the-queue") sim.add(proc, queue) sim.run() queue.pop() sim.run(10) check_log( auto_logger, (logging.INFO, 0.0, "", "Simulator", sim.name, "add", dict(fn=proc, args=(queue, ), kwargs={})), (logging.INFO, 0.0, "", "Simulator", sim.name, "run", dict(duration=inf)), (logging.INFO, 0.0, "the-process", "Queue", "the-queue", "join", {}), (logging.INFO, 0.0, "the-process", "Process", "the-process", "pause", {}), (logging.INFO, 0.0, "", "Simulator", sim.name, "stop", {}), (logging.INFO, -1.0, "", "Queue", "the-queue", "pop", dict(process="the-process")), (logging.INFO, -1.0, "", "Process", "the-process", "resume", {}), (logging.INFO, 0.0, "", "Simulator", sim.name, "run", dict(duration=10.0)), (logging.INFO, 0.0, "the-process", "Process", "the-process", "advance", dict(delay=100.0)), (logging.INFO, 10.0, "", "Simulator", sim.name, "stop", {}))
def test_signal_already_on(): sim = Simulator() signal = Signal().turn_on() log = [] expectation = [1.0] sim.add(wait_for, signal, expectation, 1.0, log) sim.run() assert expectation == log
def run_resource_test_incoherent(num_take: int, num_release: int): sim = Simulator() resource = Resource(5) sim.add(take_M_release_N, resource, num_take, num_release) with pytest.raises(ValueError): sim.run() assert resource.num_instances_free >= 0 assert resource.num_instances_total == 5
def run_test_queue_join_pop(queue: Queue) -> List[int]: sim = Simulator() log: List[int] = [] for n in range(10): sim.add(queuer, n, queue, log, float(n + 1)) sim.add(dequeueing, queue, 100.0) sim.run() return log
def test_schedule_multiple_events(): ll = [] sim = Simulator() sim._schedule(1.0, append, 1, ll) sim._schedule(0.7, append, 2, ll) sim._schedule(10.0, append, 3, ll) sim.run() assert ll == [2, 1, 3] assert sim.now() == 10.0
def run_test_resource(resource_taker: ResourceTaker, num_instances: int, expected: List[float]) -> None: sim = Simulator() resource = Resource(num_instances) log: List[float] = [] for n in range(8): sim.add(resource_taker, resource, float(n + 1), log) sim.run() assert expected == pytest.approx(log)
def test_signal_wait_a_while(): sim = Simulator() signal = Signal().turn_off() log = [] expectation = [3.0, 4.0] sim.add(wait_for, signal, expectation, 1.0, log) sim._schedule(3.0, signal.turn_on) sim.run() assert expectation == log
def test_probing_current_process(): def proc(): assert Process.current_exists() assert not Process.current_exists() sim = Simulator() sim.add(proc) sim.run() assert not Process.current_exists()
def test_resource_release_while_holding_none(): def proc(resource: Resource) -> None: resource.release() pytest.fail() sim = Simulator() resource = Resource(1) sim.add(proc, resource) with pytest.raises(RuntimeError): sim.run()
def test_happens_named(): @happens([5], name="my-process") def process(): advance(5) sim = Simulator() proc = sim.add(process) sim.run() assert proc.local.name == "my-process" assert 10.0 == pytest.approx(sim.now())
def test_getting_current_process(): def proc(): assert isinstance(Process.current(), Process) sim = Simulator() sim.add(proc) sim.run() with pytest.raises(TypeError): proc()
def run_test_process_add(launcher): when_last = 0.0 def last_proc(): nonlocal when_last when_last = now() sim = Simulator() sim.add(launcher, last_proc) sim.run() assert pytest.approx(50.0) == when_last
def test_happens(): sim = Simulator() log = [] @happens(repeat(2.0, 5)) def process(the_log): the_log.append(now()) sim.add(process, log) sim.run() assert pytest.approx([2.0, 4.0, 6.0, 8.0, 10.0]) == log
def test_queue_length(): sim = Simulator() queue = Queue() assert 0 == len(queue) log = [] for n in range(10): sim.add(queuer, n, queue, log, float(n + 1)) sim.run() assert 10 == len(queue) sim.add(dequeueing, queue, 0.0) sim.run() assert 0 == len(queue)
def do_test_with_interrupter(main, ll_expected, now_expected): def interrupter(main): advance(10.1) main.interrupt() ll = [] sim = Simulator() proc_main = sim.add(main, ll) sim.add(interrupter, proc_main) sim.run() assert ll == pytest.approx(ll_expected) assert sim.now() == pytest.approx(now_expected)
def test_process_adding_process(): log = [] def proc(delay): advance(delay) log.append(now()) add(proc, delay * 2.0) sim = Simulator() sim.add(proc, 1.0) sim.run(200.0) assert [1.0, 3.0, 7.0, 15.0, 31.0, 63.0, 127.0] == pytest.approx(log)
def run_test_tagged_add(tagged_launcher, stop): when_last = 0.0 def last_proc(): nonlocal when_last when_last = now() assert Process.current().has_tag(TestTag.ALICE) sim = Simulator() sim.add(tagged_launcher, last_proc) sim.run() assert pytest.approx(stop) == when_last
def test_signal_toggling(): sim = Simulator() signal = Signal().turn_off() log = [] expectation = [3.0, 4.0, 10.0, 13.0, 14.0, 15.0] sim.add(wait_for, signal, expectation, 1.0, log) sim._schedule(3.0, signal.turn_on) sim._schedule(4.5, signal.turn_off) sim._schedule(10.0, signal.turn_on) sim._schedule(10.1, signal.turn_off) sim._schedule(13.0, signal.turn_on) sim.run() assert expectation == log
def test_process_advance(): def process(ll): ll.append(now()) advance(1.0) ll.append(now()) advance(5.0) ll.append(now()) ll = [] sim = Simulator() sim.add(process, ll) sim.run() assert ll == [0.0, 1.0, 6.0]
def test_schedule_recurring(): ll = [0] def _append(): if sim.now() <= 10.0: ll.append(ll[-1] + 1) sim._schedule(1.0, _append) else: sim.stop() sim = Simulator() sim._schedule(1.0, _append) sim.run() assert sim.now() == 11.0 assert ll == list(range(11))
def test_tracker_lifecycle(): def capture_pass(progress, rt_remaining, mc): pass sim = Simulator() tracker = sim.add(track_progress, sim_time, [1000.0], 100.0, capture_pass) assert has_tracker(sim, tracker) def check_tracker(): advance(150) assert has_tracker(sim, tracker) sim.add(check_tracker) sim.run(10000.0) assert not has_tracker(sim, tracker) assert sim.now() == pytest.approx(1000.0)
def test_progress_real_time(): log = [] def capture(_progress_min, rt_remaining, mc): log.append(rt_remaining) def sleeper(interval, rt_delay): while True: advance(interval) sim = Simulator() sim.add(track_progress, sim_time, [100.0], 20.0, capture) sim.add(sleeper, 10.0, 0.1) sim.run() assert log == pytest.approx([0.8, 0.6, 0.4, 0.2, 0.0])
def test_process_multiple(): def tick(name, period, log): while True: advance(period) log.append((int(now()), name)) sim = Simulator() log = [] sim.add(tick, "three", 3.0, log) sim.add(tick, "seven", 7.0, log) sim.add(tick, "eleven", 11.0, log) sim.run(100.0) expectation = [(n, "eleven") for n in range(11, 100, 11)] expectation += [(n, "seven") for n in range(7, 100, 7)] expectation += [(n, "three") for n in range(3, 100, 3)] assert sorted(expectation, key=lambda p: p[0]) == log
def test_schedule_functions(): def f1(sim, results): res = f"1 + {sim.now()}" results.append(res) def f2(sim, results): res = f"2 + {sim.now()}" results.append(res) sim = Simulator() results = [] sim._schedule(1, f1, sim, results) sim._schedule(2, f2, sim, results) sim._schedule(3, f1, sim, results) sim.run() assert ['1 + 1.0', '2 + 2.0', '1 + 3.0'] == results
def test_select_one_on(): has_passed = False def selecter(sigs: List[Signal]): nonlocal has_passed select(*sigs) has_passed = True sim = Simulator() signals = [Signal().turn_off() for n in range(5)] sim.add(selecter, signals) sim.run() assert not has_passed signals[3].turn_on() sim.run() assert has_passed
def test_signal_waiter_turning_off(): def waiter_turning_off(signal: Signal, log: List[float]): signal.wait() signal.turn_off() log.append(now()) sim = Simulator() signal = Signal().turn_off() log_time = [] for n in range(5): sim.add(waiter_turning_off, signal, log_time) schedule_signal_on = [4.0, 9.0, 9.1, 200.0, 3000.0] for moment in schedule_signal_on: sim._schedule(moment, signal.turn_on) sim.run() assert schedule_signal_on == pytest.approx(log_time)
def test_resource_timeout(): resource = Resource(1) log = [] def take_but_balk(name, delay_balk): try: with resource.using(timeout=delay_balk): advance(20.0) log.append((name, "finish")) except Timeout: log.append((name, "balk")) sim = Simulator() sim.add(take_but_balk, "a", 10.0) sim.add_in(5.0, take_but_balk, "b", 10.0) sim.run() assert log == [("b", "balk"), ("a", "finish")]