def test_parse_misc_actions(): proclang = ''' main: 1. CONTROL: Set injector_valve to open 2. CONTROL: [p1 < 10] Disarm the remote control system 3. PRIMARY: Approach the launch tower, disconnect the cylinder, and replace the cap 4. OPS: [60s] Proceed with teardown ''' suite = top.proclang.parse(proclang) expected_suite = top.ProcedureSuite([ top.Procedure('main', [ top.ProcedureStep( '1', top.StateChangeAction('injector_valve', 'open'), [ (top.Less('p1', 10), top.Transition('main', '2')) ], 'CONTROL'), top.ProcedureStep( '2', top.MiscAction('Disarm the remote control system'), [(top.Immediate(), top.Transition('main', '3'))], 'CONTROL'), top.ProcedureStep( '3', top.MiscAction( 'Approach the launch tower, disconnect the cylinder, and replace the cap' ), [(top.WaitFor(60e6), top.Transition('main', '4'))], 'PRIMARY'), top.ProcedureStep('4', top.MiscAction('Proceed with teardown'), [], 'OPS') ]) ]) assert suite == expected_suite
def test_parse_from_file(): filepath = os.path.join(os.path.dirname(__file__), 'example.proc') suite = top.proclang.parse_from_file(filepath) expected_suite = top.ProcedureSuite([ top.Procedure('main', [ top.ProcedureStep( '1', top.StateChangeAction('series_fill_valve', 'closed'), [(top.WaitFor(5e6), top.Transition('main', '2'))], 'PRIMARY'), top.ProcedureStep( '2', top.StateChangeAction('supply_valve', 'open'), [(top.Less('p1', 600), top.Transition('abort_1', '1')), (top.Greater('p1', 1000), top.Transition('abort_2', '1')), (top.Immediate(), top.Transition('main', '3'))], 'PRIMARY'), top.ProcedureStep( '3', top.StateChangeAction('series_fill_valve', 'open'), [(top.Immediate(), top.Transition('main', '4'))], 'PRIMARY'), top.ProcedureStep( '4', top.StateChangeAction('remote_fill_valve', 'open'), [ (top.WaitFor(180e6), top.Transition('main', '5')) ], 'PRIMARY'), top.ProcedureStep( '5', top.StateChangeAction('remote_fill_valve', 'closed'), [(top.Immediate(), top.Transition('main', '6'))], 'PRIMARY'), top.ProcedureStep( '6', top.StateChangeAction('remote_vent_valve', 'open'), [(top.Immediate(), top.Transition('main', '7'))], 'PRIMARY'), top.ProcedureStep('7', top.MiscAction('Proceed with teardown'), [], 'OPS') ]), top.Procedure('abort_1', [ top.ProcedureStep( '1', top.StateChangeAction('supply_valve', 'closed'), [ (top.WaitFor(10e6), top.Transition('abort_1', '2')) ], 'SECONDARY'), top.ProcedureStep( '2', top.StateChangeAction('remote_vent_valve', 'open'), [ (top.Immediate(), top.Transition('abort_1', '3')) ], 'SECONDARY'), top.ProcedureStep('3', top.MiscAction('Proceed with teardown'), [], 'OPS') ]), top.Procedure('abort_2', [ top.ProcedureStep( '1', top.StateChangeAction('supply_valve', 'closed'), [ (top.Immediate(), top.Transition('abort_2', '2')) ], 'CONTROL'), top.ProcedureStep( '2', top.StateChangeAction('line_vent_valve', 'open'), [ (top.Immediate(), top.Transition('abort_2', '3')) ], 'CONTROL'), top.ProcedureStep('3', top.MiscAction('Proceed with teardown'), [], 'OPS') ]), ]) assert suite == expected_suite
def test_jump_to_step_normal(): plumb_b = PlumbingBridge() control_b = ControlsBridge(plumb_b) proc_b = ProceduresBridge(plumb_b, control_b) procedure = top.Procedure('main', [ top.ProcedureStep('1', top.StateChangeAction('injector_valve', 'open'), [(top.Immediate(), top.Transition('main', '2'))], 'PRIMARY'), top.ProcedureStep( '2', top.StateChangeAction('injector_valve', 'closed'), [(top.Immediate(), top.Transition('main', '3'))], 'PRIMARY'), top.ProcedureStep( '3', top.StateChangeAction('injector_valve', 'closed'), [(top.Immediate(), top.Transition('main', '4'))], 'PRIMARY'), top.ProcedureStep('4', top.MiscAction('Approach the launch tower'), [], 'SECONDARY') ]) proc_b.load_suite(top.ProcedureSuite([procedure])) plumb_eng = make_plumbing_engine() plumb_b.load_engine(plumb_eng) proc_eng = proc_b._proc_eng assert proc_eng.current_step == procedure.step_list[0] assert proc_eng.step_position == top.StepPosition.Before proc_b.procJump("2") assert proc_eng.current_step == procedure.step_list[1] assert proc_eng.step_position == top.StepPosition.After proc_b.procJump("4") assert proc_eng.current_step == procedure.step_list[3] assert proc_eng.step_position == top.StepPosition.After
def test_proc_bridge_procedure_step_affects_plumbing(): plumb_b = PlumbingBridge() control_b = ControlsBridge(plumb_b) proc_b = ProceduresBridge(plumb_b, control_b) procedure = top.Procedure('main', [ top.ProcedureStep('1', top.StateChangeAction('injector_valve', 'open'), [(top.Immediate(), top.Transition('main', '2'))], 'PRIMARY'), top.ProcedureStep( '2', top.StateChangeAction('injector_valve', 'closed'), [(top.Immediate(), top.Transition('main', '3'))], 'PRIMARY'), top.ProcedureStep('3', top.MiscAction('Approach the launch tower'), [], 'SECONDARY') ]) proc_b.load_suite(top.ProcedureSuite([procedure])) plumb_eng = make_plumbing_engine() plumb_b.load_engine(plumb_eng) assert plumb_eng.current_state('injector_valve') == 'closed' proc_b.procStepForward() assert plumb_eng.current_state('injector_valve') == 'open' proc_b.procStepForward() assert plumb_eng.current_state('injector_valve') == 'closed'
def test_time_advance(): plumb_b = PlumbingBridge() control_b = ControlsBridge(plumb_b) proc_b = ProceduresBridge(plumb_b, control_b) procedure = top.Procedure('main', [ top.ProcedureStep('1', top.StateChangeAction('injector_valve', 'open'), [(top.Less('A', 75), top.Transition('main', '2'))], 'PRIMARY'), top.ProcedureStep('2', top.MiscAction('Approach the launch tower'), [], 'SECONDARY') ]) proc_b.load_suite(top.ProcedureSuite([procedure])) plumb_eng = make_plumbing_engine() plumb_b.load_engine(plumb_eng) tol = 0.01 proc_eng = proc_b._proc_eng proc_b.procStepForward() # execute step 1 assert not proc_eng.ready_to_proceed() assert plumb_eng.current_pressures('A') == 100 assert plumb_eng.current_pressures('B') == 0 plumb_b.timeAdvance() assert proc_eng.ready_to_proceed() # We expect pressures to equalize at 50 once the system is steady assert abs(plumb_eng.current_pressures('A') - 50) < tol assert abs(plumb_eng.current_pressures('B') - 50) < tol
def test_proc_bridge_procedure_controls_advance_procedure(): plumb_b = MockPlumbingBridge() proc_b = ProceduresBridge(plumb_b) procedure = top.Procedure('main', [ top.ProcedureStep('1', top.StateChangeAction('injector_valve', 'open'), [(top.Immediate(), top.Transition('main', '2'))], 'PRIMARY'), top.ProcedureStep('2', top.StateChangeAction('vent_valve', 'closed'), [ (top.WaitFor(100), top.Transition('main', '3')) ], 'PRIMARY'), top.ProcedureStep('3', top.MiscAction('Approach the launch tower'), [], 'SECONDARY') ]) proc_b.load_suite(top.ProcedureSuite([procedure])) proc_eng = proc_b._proc_eng assert proc_eng.current_step == procedure.step_list[0] assert proc_eng.step_position == top.StepPosition.Before proc_b.procStepForward() assert proc_eng.current_step == procedure.step_list[0] assert proc_eng.step_position == top.StepPosition.After proc_b.procStepForward() assert proc_eng.current_step == procedure.step_list[1] assert proc_eng.step_position == top.StepPosition.After proc_b.procStepForward() # does nothing; condition is not satisfied assert proc_eng.current_step == procedure.step_list[1] assert proc_eng.step_position == top.StepPosition.After proc_b.procStop() assert proc_eng.current_step == procedure.step_list[0] assert proc_eng.step_position == top.StepPosition.Before
def misc_action(self, data): """ Process `misc_action` nodes in the parse tree. `data` is a list of the form [action]. """ return top.MiscAction(data[0])
def test_time_stop(): plumb_b = PlumbingBridge() plumb_b.step_size = 0.1e6 control_b = ControlsBridge(plumb_b) proc_b = ProceduresBridge(plumb_b, control_b) procedure = top.Procedure('main', [ top.ProcedureStep('1', top.StateChangeAction('injector_valve', 'open'), [(top.WaitFor(0.1e6), top.Transition('main', '2'))], 'PRIMARY'), top.ProcedureStep('2', top.MiscAction('Approach the launch tower'), [], 'SECONDARY') ]) proc_b.load_suite(top.ProcedureSuite([procedure])) plumb_eng = make_plumbing_engine() plumb_b.load_engine(plumb_eng) proc_eng = proc_b._proc_eng proc_b.procStepForward() # execute step 1 assert not proc_eng.ready_to_proceed() # Time hasn't advanced yet, so pressures should be the same assert plumb_eng.current_pressures('A') == 100 assert plumb_eng.current_pressures('B') == 0 plumb_b.timeStepForward() # time == 0.1s assert proc_eng.ready_to_proceed() # Valve is open, so pressures should start dropping assert plumb_eng.current_pressures('A') < 100 assert plumb_eng.current_pressures('B') > 0 proc_b.procStop() plumb_b.timeStop() # Everything should now be as it started assert proc_eng.current_step.step_id == '1' assert plumb_eng.current_state('injector_valve') == 'closed' assert plumb_eng.current_pressures('A') == 100 assert plumb_eng.current_pressures('B') == 0 proc_b.procStepForward() # execute step 1 assert not proc_eng.ready_to_proceed() # Time hasn't advanced yet, so pressures should be the same assert plumb_eng.current_pressures('A') == 100 assert plumb_eng.current_pressures('B') == 0 plumb_b.timeStepForward() # time == 0.1s assert proc_eng.ready_to_proceed() # Valve is open, so pressures should start dropping assert plumb_eng.current_pressures('A') < 100 assert plumb_eng.current_pressures('B') > 0
def test_execute_custom_action(): plumb_eng = one_component_engine() proc_eng = top.ProceduresEngine(plumb_eng) action = top.StateChangeAction('c1', 'closed') assert plumb_eng.current_state('c1') == 'open' proc_eng.execute(action) assert plumb_eng.current_state('c1') == 'closed' misc_action = top.MiscAction('Approach the tower') proc_eng.execute(misc_action) assert plumb_eng.current_state('c1') == 'closed'
def test_proc_bridge_load_suite(): plumb_b = MockPlumbingBridge() proc_b = ProceduresBridge(plumb_b) procedure = top.Procedure('main', [ top.ProcedureStep('1', top.StateChangeAction('injector_valve', 'open'), [(top.Immediate(), top.Transition('main', '2'))], 'PRIMARY'), top.ProcedureStep('2', top.MiscAction('Approach the launch tower'), [], 'SECONDARY') ]) suite = top.ProcedureSuite([procedure]) proc_b.load_suite(suite) assert proc_b._proc_eng._suite == suite assert proc_b.steps.procedure == procedure
def test_procedure_step_affects_component_state(): plumb_b = PlumbingBridge() control_b = ControlsBridge(plumb_b) proc_b = ProceduresBridge(plumb_b, control_b) procedure = top.Procedure('main', [ top.ProcedureStep('1', top.StateChangeAction('injector_valve', 'open'), [(top.Immediate(), top.Transition('main', '2'))], 'PRIMARY'), top.ProcedureStep( '2', top.StateChangeAction('injector_valve', 'closed'), [(top.Immediate(), top.Transition('main', '3'))], 'PRIMARY'), top.ProcedureStep('3', top.MiscAction('Approach the launch tower'), [], 'SECONDARY') ]) proc_b.load_suite(top.ProcedureSuite([procedure])) plumb_eng = make_plumbing_engine() plumb_b.load_engine(plumb_eng) control_b.refresh() proc_eng = proc_b._proc_eng assert proc_eng.current_step == procedure.step_list[0] assert proc_eng.step_position == top.StepPosition.Before proc_b.procStepForward() assert (control_b.states[0] == "open") assert proc_eng.current_step == procedure.step_list[0] assert proc_eng.step_position == top.StepPosition.After proc_b.procStepForward() assert (control_b.states[0] == "closed") assert proc_eng.current_step == procedure.step_list[1] assert proc_eng.step_position == top.StepPosition.After proc_b.procStepForward() assert (control_b.states[0] == "closed") proc_b.procStop() assert proc_eng.current_step == procedure.step_list[0] assert proc_eng.step_position == top.StepPosition.Before
def test_steps_model_get_data(): procedure = top.Procedure('main', [ top.ProcedureStep('1', top.StateChangeAction('injector_valve', 'open'), [ (top.Immediate(), top.Transition('main', '2')) ], 'PRIMARY'), top.ProcedureStep('2', top.MiscAction('Approach the launch tower'), [], 'SECONDARY') ]) model = ProcedureStepsModel(procedure) wrapper = ProcedureConditionWrapper(top.Immediate(), top.Transition('main', '2')) idx_0 = model.createIndex(0, 0) assert model.data(idx_0, ProcedureStepsModel.ActionRoleIdx) == 'Set injector_valve to open' assert model.data(idx_0, ProcedureStepsModel.OperatorRoleIdx) == 'PRIMARY' assert model.data(idx_0, ProcedureStepsModel.ConditionsRoleIdx) == [wrapper] idx_1 = model.createIndex(1, 0) assert model.data(idx_1, ProcedureStepsModel.ActionRoleIdx) == 'Approach the launch tower' assert model.data(idx_1, ProcedureStepsModel.OperatorRoleIdx) == 'SECONDARY' assert model.data(idx_1, ProcedureStepsModel.ConditionsRoleIdx) == []
def test_control_panel_initialization(): plumb_b = PlumbingBridge() control_b = ControlsBridge(plumb_b) proc_b = ProceduresBridge(plumb_b, control_b) procedure = top.Procedure('main', [ top.ProcedureStep('1', top.StateChangeAction('injector_valve', 'open'), [(top.Immediate(), top.Transition('main', '2'))], 'PRIMARY'), top.ProcedureStep( '2', top.StateChangeAction('injector_valve', 'closed'), [(top.Immediate(), top.Transition('main', '3'))], 'PRIMARY'), top.ProcedureStep('3', top.MiscAction('Approach the launch tower'), [], 'SECONDARY') ]) proc_b.load_suite(top.ProcedureSuite([procedure])) plumb_eng = make_plumbing_engine() plumb_b.load_engine(plumb_eng) control_b.refresh() assert (control_b.toggleable_components == ['injector_valve']) assert (control_b.states[0] == "closed")
def test_transitions_respects_procedure_identifier(): plumb_eng = one_component_engine() action = top.MiscAction('Do nothing') s1 = top.ProcedureStep( 's1', action, [(NeverSatisfied(), top.Transition('p1', 'same_name')), (top.Immediate(), top.Transition('p2', 'same_name'))], 'PRIMARY') same_name_1 = top.ProcedureStep('same_name', action, [], 'PRIMARY') same_name_2 = top.ProcedureStep('same_name', action, [], 'PRIMARY') proc_1 = top.Procedure('p1', [s1, same_name_1]) proc_2 = top.Procedure('p2', [same_name_2]) proc_suite = top.ProcedureSuite([proc_1, proc_2], 'p1') proc_eng = top.ProceduresEngine(plumb_eng, proc_suite) proc_eng.execute_current() assert proc_eng.current_procedure_id == 'p1' assert proc_eng.current_step.step_id == 's1' proc_eng.next_step() assert proc_eng.current_procedure_id == 'p2' assert proc_eng.current_step.step_id == 'same_name'
def test_action_types(): a1 = top.StateChangeAction('p1', 'open') a2 = top.MiscAction('approach the tower') assert isinstance(a1, top.Action) assert isinstance(a2, top.Action)