def test_interruption_in_machines_with_sequential_state(capsys):

    ws1 = WaitState("ws1", 0.2)
    ws2 = WaitState("ws2", 0.2)
    ps1 = PrintState("ps1", "Print1")
    es = IdleState("es")
    iss = IdleState("iss")
    sm = SequentialState("sm", children=[ws1, ws2, ps1])
    sm.add_transition_on_success(es)
    sm.add_transition(lambda s, b: s._curr_child.checkName('ws2'), iss)

    exe = Machine("exe", sm, ["es", "iss"], rate=100)
    exe.run()
    assert exe._exception_raised_state_name == ""
    assert exe._internal_exception is None
    assert exe._status == StateStatus.SUCCESS
    assert not exe._run_thread.is_alive()
    assert exe._curr_state._name == 'iss'
    assert exe.is_end()
    assert capsys.readouterr().out == ""
    assert not sm._run_thread.is_alive()
    assert not ws1._run_thread.is_alive()
    assert not ws2._run_thread.is_alive()
    assert sm._status == StateStatus.INTERRUPTED
    assert ws2._status == StateStatus.INTERRUPTED
    assert ws1._status == StateStatus.SUCCESS
    assert ps1._status == StateStatus.UNKNOWN
    assert ws2.checkStatus(StateStatus.INTERRUPTED)
    assert ws1.checkStatus(StateStatus.SUCCESS)
Ejemplo n.º 2
0
def test_object_set_get(capsys):
    class SetState(State):
        def execute(self, board: Board):
            obj = {'hello': [1, 2, 3], 'name': {'first': 'test'}}
            board.set('obj', obj)
            obj['name'] = {}
            return StateStatus.SUCCESS

    class GetState(State):
        def execute(self, board):
            obj = board.get('obj')
            assert obj['hello'] == [1, 2, 3]
            assert obj['name']['first'] == 'test'
            return StateStatus.SUCCESS

    s = SetState('s')
    g = GetState('g')
    w = WaitState('w', 1)

    s.add_transition_on_success(w)
    w.add_transition_on_success(g)
    exe = Machine('xe', s, end_state_ids=['g'])
    exe.run()
    assert exe.is_end()
    assert exe._curr_state._status == StateStatus.SUCCESS
Ejemplo n.º 3
0
def test_atleastone_interrupt(capsys):

    interrupted = False

    class WaitAndPrint(State):
        def execute(self, board: Board) -> typing.Optional[StateStatus]:
            time.sleep(0.5)
            if self.is_interrupted():
                nonlocal interrupted
                interrupted = True
                return StateStatus.INTERRUPTED
            print("HelloWorld")
            return StateStatus.SUCCESS

    one = AtLeastOneState("one", children=[
        PrintState('p5', "ps5"),
        WaitAndPrint("ws")
    ])
    es = IdleState("endState")
    one.add_transition_on_success(es)
    exe = Machine("xe", one, end_state_ids=["endState"], rate=10)
    exe.run()

    assert capsys.readouterr().out == "ps5\n"
    assert interrupted
Ejemplo n.º 4
0
def test_end_case():
    ps1 = PrintState("ps1", "Hello World")
    es = DummyState("endState")
    ps1.add_transition_on_success(es)
    exe = Machine("xe", ps1, end_state_ids=["endState"], rate=10)
    exe.run()
    assert exe.is_end()
Ejemplo n.º 5
0
def test_interrupt_machine(capsys):
    s1 = WaitState('s1', 1.1)
    s2 = DummyState('s2')
    s1.add_transition_on_success(s2)
    mac = Machine("mac", s1, ["s2"], debug=True, rate=1)
    mac.start(None)
    assert mac.interrupt()
Ejemplo n.º 6
0
def test_simple_machine(capsys):
    ps1 = PrintState("ps1", "print1")
    ps2 = PrintState("ps2", "print2")
    ps1.add_transition_on_success(ps2)
    exe = Machine("xe", ps1, end_state_ids=["ps2"], rate=10)
    b = Board()
    exe.run(b)
    assert exe.is_end()
    assert capsys.readouterr().out == "print1\nprint2\n"
Ejemplo n.º 7
0
def test_print_state(capsys):

    print_text = "this is a print_text"
    ps = PrintState("p1", print_text)
    es = IdleState("endState")
    ps.add_transition_on_success(es)
    exe = Machine("xe", ps, end_state_ids=["endState"], rate=10)
    exe.run()
    captured = capsys.readouterr()
    assert captured.out == print_text + '\n'
def test_machine_rate_fast():
    ps1 = PrintState("ps1", "print1")  # execute at second 0
    ps2 = PrintState("ps1", "print2")  # execute at second 0.1
    es = DummyState("endState")  # execute at second 0.2
    ps1.add_transition_on_success(ps2)
    ps2.add_transition_on_success(es)
    exe = Machine("xe", ps1, end_state_ids=["endState"], rate=10)
    start_time = time.time()
    exe.run()
    duration = time.time() - start_time
    assert 0.2 == pytest.approx(duration, abs=1e-2)
Ejemplo n.º 9
0
def test_parse_debug_info():

    from behavior_machine.library import SequentialState, IdleState, WaitState
    from behavior_machine.core import Machine

    s1 = IdleState('s1')
    exe = Machine('exe', s1)
    info = exe.get_debug_info()
    parse_str = logging.parse_debug_info(info)
    assert parse_str[0] == 'exe(Machine) -- UNKNOWN'
    assert parse_str[1] == '  -> s1(IdleState) -- UNKNOWN'
Ejemplo n.º 10
0
def test_wait_state():

    s1 = WaitState("s1", 2)
    s2 = IdleState("s2")
    s1.add_transition_on_success(s2)

    exe = Machine("test", s1, end_state_ids=['s2'], rate=10)

    start_time = time.time()
    exe.run()
    duration = time.time() - start_time
    # Because the waut these are executed, its hard to know the margin
    assert duration == pytest.approx(2, rel=0.1)
Ejemplo n.º 11
0
def test_chain_case():
    s1 = DummyState("s1")
    s2 = DummyState("s2")
    s1.add_transition_on_success(s2)
    s3 = DummyState("s3")
    s2.add_transition_on_success(s3)
    exe = Machine("xe", s1, end_state_ids=["s3"], rate=10)
    b = Board()
    exe.start(b, manual_exec=True)
    exe.update(b, True)
    assert not exe.is_end()
    exe.update(b, True)
    assert exe.is_end()
def test_end_case_delay(capsys):
    ps1 = PrintState("ps1", "Hello World")
    class EndState(State):
        def execute(self, board):
            time.sleep(0.5)
            print('completed')
            return StateStatus.SUCCESS
    es = EndState('endState')
    ps1.add_transition_on_success(es)
    exe = Machine("xe", ps1, end_state_ids=["endState"], rate=10)
    exe.run()
    assert exe.is_end()
    assert capsys.readouterr().out == "Hello World\ncompleted\n"
Ejemplo n.º 13
0
def test_machine_rate_fast():
    w1 = WaitState("w1", 0.05)  # execute at second 0
    w2 = WaitState("w2", 0.05)  # execute at second 0.1s
    es = DummyState("endState")  # execute at second 0.2
    w1.add_transition_on_success(w2)
    w2.add_transition_on_success(es)
    exe = Machine("xe", w1, end_state_ids=["endState"], rate=10)
    start_time = time.time()
    exe.run()
    duration = time.time() - start_time
    assert pytest.approx(duration, abs=1e-2) == 0.2
    assert w1._status == StateStatus.SUCCESS
    assert w2._status == StateStatus.SUCCESS
Ejemplo n.º 14
0
def test_machine_with_exception_in_transition(capsys):

    is1 = DummyState('d1')
    is2 = DummyState('d2')

    is1.add_transition(lambda s, b: s.unknown(), is2)

    mac = Machine("mac", is1, ["is2"])
    mac.run()

    assert mac._status == StateStatus.EXCEPTION
    assert not mac._run_thread.is_alive()
    assert not is1._run_thread.is_alive()
    assert is2._run_thread is None  # Never reach is2
def test_nested_sequential_state(capsys):
    ps1 = PrintState("ps1", "Print1")
    ps2 = PrintState("ps2", "Print2")
    ps3 = PrintState("ps3", "Print3")
    ps4 = PrintState("ps4", "Print4")
    es = IdleState("endState")

    sm = SequentialState("sm", children=[ps3, ps2])
    sm2 = SequentialState("sm2", children=[ps4, sm, ps1])
    sm2.add_transition_on_success(es)
    mach = Machine("xe", sm2, end_state_ids=['endState'], rate=10)
    mach.run()

    assert capsys.readouterr().out == "Print4\nPrint3\nPrint2\nPrint1\n"
Ejemplo n.º 16
0
def test_parallel_one_state_exception(capsys):
    class ExceptionAfter1SecState(State):
        def execute(self, board):
            time.sleep(1)
            return StateStatus.EXCEPTION

    ws = WaitState("ws1", 5)
    fs = ExceptionAfter1SecState("fs")
    es = IdleState("es")
    fes = IdleState("fs-terminal")
    pm = ParallelState('pm', [ws, fs])
    pm.add_transition_on_success(es)
    pm.add_transition_on_failed(fes)
    exe = Machine("main_machine",
                  pm,
                  end_state_ids=['es', 'fs-terminal'],
                  rate=10)

    # run machine and see how it reacts
    exe.start(None)
    # wait for 0.5 second to see it is still running
    assert not exe.wait(0.5)
    assert exe.check_status(StateStatus.RUNNING)
    assert exe._curr_state.check_name('pm')
    # at this point, it should throw or raise the exception
    # wait another 1.5 seconds
    assert exe.wait(1.5)
    assert exe.check_status(StateStatus.EXCEPTION)
    assert not pm._run_thread.is_alive()
def test_debugging_machine(capsys):

    from behavior_machine import logging
    logging.add_fs('capsys', sys.stdout)
    s1 = WaitState('s1', 1.1)
    s2 = DummyState('s2')
    s1.add_transition_on_success(s2)
    mac = Machine("mac", s1, ["s2"], debug=True, rate=1)
    mac.run()
    assert mac.is_end()
    assert capsys.readouterr().out == ("[Base] mac(Machine) -- RUNNING\n"
                                       "  -> s1(WaitState) -- RUNNING\n"
                                       "[Base] mac(Machine) -- RUNNING\n"
                                       "  -> s2(DummyState) -- SUCCESS\n")
Ejemplo n.º 18
0
def test_interrupt_in_parallel_state(capsys):
    ws = WaitState("ws1", 1)
    ws2 = WaitState("ws2", 2)
    es = IdleState("es")
    pm = ParallelState('pm', [ws, ws2])
    pm.add_transition_on_success(es)
    pm.add_transition_after_elapsed(es, 0.1)
    exe = Machine("main_machine", pm, end_state_ids=['es'], rate=10)
    # run machine
    exe.start(None)
    # because of the elapsed transition, the machine will immediate transition to the end state in 0.1 seconds
    assert exe.wait(0.2)
    assert ws._status == StateStatus.INTERRUPTED
    assert ws2._status == StateStatus.INTERRUPTED
    assert not pm._run_thread.is_alive()
Ejemplo n.º 19
0
def test_flow_into_machine(capsys):

    test_phrase = "test_flow_into_machine"

    class OnlyState(State):
        def execute(self, board):
            assert self.flow_in == test_phrase
            print("only-state")
            return StateStatus.SUCCESS

    os = OnlyState("only")
    mac = Machine("mac", os, ["only"])
    mac.run(flow_in=test_phrase)
    assert mac.is_end()
    assert capsys.readouterr().out == "only-state\n"
Ejemplo n.º 20
0
def test_machine_with_exception_in_transition_with_zombie_states(capsys):

    ws1 = WaitState('ws1', 10)
    is2 = DummyState('d2')

    ws1.add_transition(lambda s, b: s.unknown(), is2)

    mac = Machine("mac", ws1, ["is2"])
    mac.run()
    assert mac._status == StateStatus.EXCEPTION
    # this is an interrupted, because exception happen at higher level
    assert ws1._status == StateStatus.INTERRUPTED
    assert not mac._run_thread.is_alive()
    assert not ws1._run_thread.is_alive()
    assert is2._run_thread is None  # Never reach it
Ejemplo n.º 21
0
def test_transition_on_failed(capsys):
    class failedState(State):
        def execute(self, board):
            return StateStatus.FAILED

    fs = failedState('fs')
    ps1 = PrintState("ps1", "success")
    ps2 = PrintState("ps2", "failed")
    fs.add_transition_on_success(ps1)
    fs.add_transition_on_failed(ps2)
    exe = Machine("xe", fs, end_state_ids=["ps1", "ps2"], rate=10)
    exe.run(None)
    assert exe.is_end()
    assert exe._curr_state.check_name("ps2")
    assert capsys.readouterr().out == "failed\n"
def test_sequential_state(capsys):

    ps1 = PrintState("ps1", "Print1")
    ps2 = PrintState("ps1", "Print2")
    ps3 = PrintState("ps1", "Print3")
    es = IdleState("endState")

    sm = SequentialState("sm", children=[ps2, ps3])
    sm.add_children(ps1)

    sm.add_transition_on_success(es)
    exe = Machine("xe", sm, end_state_ids=["endState"], rate=10)
    exe.run()

    assert capsys.readouterr().out == "Print2\nPrint3\nPrint1\n"
def test_interrupt_in_parallel_state(capsys):
    ws = WaitState("ws1", 1)
    ws2 = WaitState("ws2", 2)
    es = IdleState("es")
    pm = ParallelState('pm', [ws, ws2])
    pm.add_transition_on_success(es)
    pm.add_transition(lambda x, y: True, es)
    exe = Machine("main_machine", pm, end_state_ids=['es'], rate=10)
    # run machine
    exe.start(None)
    # because of the always transition, it should happen in about 10
    assert exe.wait(0.2)
    assert ws.checkStatus(StateStatus.INTERRUPTED)
    assert ws2.checkStatus(StateStatus.INTERRUPTED)
    assert not pm._run_thread.is_alive()
def test_sequential_state_success(capsys):
    ps1 = PrintState("ps1", "Print1")
    ps2 = PrintState("ps2", "Print2")
    es = IdleState("es")
    seqs = SequentialState("sm", children=[ps1, ps2])
    seqs.add_transition_on_success(es)
    exe = Machine("m1", seqs, ['es'])
    exe.run()

    assert capsys.readouterr().out == "Print1\nPrint2\n"
    assert exe.is_end()
    assert exe._curr_state == es
    assert seqs._status == StateStatus.SUCCESS
    assert ps1._status == StateStatus.SUCCESS
    assert ps2._status == StateStatus.SUCCESS
Ejemplo n.º 25
0
def make_machine(name):
    s1 = IdleState("s1")
    s2 = IdleState("s2")

    s1.add_transition_on_success(s2)

    return Machine(name, s1)
Ejemplo n.º 26
0
def test_machine_with_exception(capsys):

    ps1 = PrintState("ps1", "p1")
    re1 = RaiseExceptionState('re1')
    ps2 = PrintState("ps2", "p2")

    ps1.add_transition_on_success(re1)
    re1.add_transition_on_success(ps2)

    mac = Machine("mac", ps1, ["ps2"])
    mac.run()

    assert capsys.readouterr().out == 'p1\n'
    assert mac.check_status(StateStatus.EXCEPTION)
    assert str(mac._internal_exception) == "raiseException"
    assert mac._exception_raised_state_name == "mac.re1"
Ejemplo n.º 27
0
def test_transition_on_complete(capsys):
    class NothingState(State):
        def execute(self, board):
            print("hello")

    ds1 = DummyState("d1")
    ns = NothingState("ns")
    ds2 = DummyState("ds2")

    ds1.add_transition_on_success(ns)
    ns.add_transition_on_complete(ds2)

    exe = Machine("xe", ds1, end_state_ids=["ds2"], rate=10)
    exe.run(None)
    assert exe.is_end()
    assert exe._curr_state.check_name("ds2")
    assert capsys.readouterr().out == "hello\n"
Ejemplo n.º 28
0
def test_parallel_one_state_fails(capsys):
    class FailAfter1SecState(State):
        def execute(self, board):
            time.sleep(1)
            return StateStatus.FAILED

    ws = WaitState("ws1", 5)
    fs = FailAfter1SecState("fs")
    es = IdleState("es")
    fes = IdleState("fs-terminal")
    pm = ParallelState('pm', [ws, fs])
    pm.add_transition_on_success(es)
    pm.add_transition_on_failed(fes)
    exe = Machine("main_machine",
                  pm,
                  end_state_ids=['es', 'fs-terminal'],
                  rate=10)

    # run machine and see how it reacts
    exe.start(None)
    # wait for one second
    assert not exe.wait(0.5)
    assert exe.check_status(StateStatus.RUNNING)
    assert exe._curr_state.check_name('pm')
    # at this point ws should be done but ws2 is still going
    # wait another one seconds
    assert exe.wait(2)
    assert exe._curr_state == fes
    assert not pm._run_thread.is_alive()
Ejemplo n.º 29
0
def test_atleastone_state(capsys):

    ps1 = PrintState('p1', "ps1")
    ws1 = WaitState("w1", 0.5)
    ps2 = PrintState('p2', "ps2")

    one = AtLeastOneState("one", children=[
        ps2,
        SequentialState("seq", children=[
            ws1,
            ps1
        ])
    ])
    es = IdleState("endState")
    one.add_transition_on_success(es)
    exe = Machine("xe", one, end_state_ids=["endState"], rate=10)
    exe.run()

    assert capsys.readouterr().out == "ps2\n"
Ejemplo n.º 30
0
def test_debugging_machine(caplog):
    import logging
    logging.basicConfig(level=logging.DEBUG)
    caplog.set_level(logging.DEBUG)

    logger = logging.getLogger(__name__)

    s1 = WaitState('s1', 1.1)
    s2 = DummyState('s2')
    s1.add_transition_on_success(s2)
    mac = Machine("mac", s1, ["s2"], debug=True, rate=1, logger=logger)
    mac.run()
    assert mac.is_end()
    assert len(caplog.records) == 3
    assert caplog.records[
        0].message == "[Base] mac(Machine) -- RUNNING\n  -> s1(WaitState) -- RUNNING"  # This is at t=0
    assert caplog.records[
        1].message == "[Base] mac(Machine) -- RUNNING\n  -> s1(WaitState) -- RUNNING"  # This is at t=1
    assert caplog.records[
        2].message == "[Base] mac(Machine) -- RUNNING\n  -> s2(DummyState) -- SUCCESS"  # At the end