1"""Unit tests for the per-run config snapshot → human names.
3The entity spellings asserted here are the ones DatabaseConfig.cpp actually writes, and
4the slot arithmetic is LoadActiveBoards' (`board_id % 10`, 0 → 10). If either moves, this
5file is where the viewer finds out.
7Run: cd webviewer && .venv/bin/python -m pytest backend/test_run_config.py -q
12from .
import config, run_config
24[boards.actuator_board_2]
32[sensor_roles_pt_board]
36[sensor_roles_pt_board_2]
39[sensor_roles_encoder_board]
43"LOX Main" = ["NC", 1, 12]
44"Fuel Vent" = ["NC", 2, 12]
54 monkeypatch.setattr(config,
"ELODIN_DIR", tmp_path)
58def snapshot(elodin_dir, run_id: str, text: str) ->
None:
59 (elodin_dir / f
"{run_id}.toml").write_text(text)
64 snapshot(elodin_dir,
"daq_20260902_120000", CONFIG_TOML)
65 return run_config.entity_labels(run_config.load(
"daq_20260902_120000"))
73 assert labels[
"PT1.CH5"] ==
"Ox Upstream"
74 assert labels[
"PT1_Cal.CH5"] ==
"Ox Upstream"
79 assert labels[
"PT2.CH1"] ==
"GSE High"
80 assert labels[
"ENC1.CH1"] ==
"Encoder 1"
81 assert "PT21.CH5" not in labels
86 assert run_config._slot(30) == 10
87 assert run_config._slot(21) == 1
92 assert labels[
"ACT2.CH1"] ==
"LOX Main"
93 assert labels[
"ACT2_Cal.CH1"] ==
"LOX Main"
94 assert labels[
"ACT_CMD.B2.CH1"] ==
"LOX Main"
108[boards.ball_valve_board]
113"Main Ball Valve" = ["NC", 1, 71]
116 labels = run_config.entity_labels(run_config.load(
"bv"))
117 assert labels[
"BV1.CH1"] ==
"Main Ball Valve"
118 assert labels[
"BV1_Cal.CH1"] ==
"Main Ball Valve"
119 assert labels[
"BV_CMD.B1.CH1"] ==
"Main Ball Valve"
120 assert "ACT1.CH1" not in labels
121 assert "ACT_CMD.B1.CH1" not in labels
122 assert labels[
"BOARD.HB_71"] ==
"Ball Valve Board"
129 "daq_20260902_120001",
130 '[boards.actuator_board]\ntype = "ACTUATOR"\nboard_id = 11\n'
131 '\n[actuator_roles]\n"Fuel Fill" = ["NC", 7]\n',
133 labels = run_config.entity_labels(run_config.load(
"daq_20260902_120001"))
134 assert labels[
"ACT1.CH7"] ==
"Fuel Fill"
141 "daq_20260902_120002",
142 '[boards.actuator_board_2]\ntype = "ACTUATOR"\nboard_id = 12\n'
143 '\n[sensor_roles_actuator_board_2]\n"Some Sense" = 1\n'
144 '\n[actuator_roles]\n"LOX Main" = ["NC", 1, 12]\n',
146 labels = run_config.entity_labels(run_config.load(
"daq_20260902_120002"))
147 assert labels[
"ACT2.CH1"] ==
"LOX Main"
152 assert labels[
"BOARD.HB_21"] ==
"PT Board #1"
153 assert labels[
"BOARD.HB_22"] ==
"PT Board #2"
155 assert labels[
"BOARD.HB_12"] ==
"Actuator Board"
156 assert labels[
"BOARD.HB_61"] ==
"Encoder Board"
161 assert run_config.label_for(
"SELF_TEST.BOARD_21.s3", labels) ==
"PT Board #1 sensor 3"
166 assert run_config.label_for(
"CONTROLLER.state", labels) ==
""
167 assert run_config.label_for(
"PT1.CH9", labels) ==
""
174 names = run_config.state_names(run_config.load(
"daq_20260902_120000"))
175 assert names[16] ==
"Burn"
176 assert names[1] ==
"Idle"
177 assert names[20] ==
"Press Standby"
182 assert run_config.state_names({})[16] ==
"Fire"
187 assert "engine_state" not in run_config.STATE_FIELDS
188 assert run_config.STATE_FIELDS == {
"current_state",
"from_state",
"to_state"}
195 assert run_config.load(
"daq_20260101_000000") == {}
196 assert run_config.entity_labels({}) == {}
201 snapshot(elodin_dir,
"daq_20260902_120003",
"[boards.pt_board\ntype = ")
202 assert run_config.load(
"daq_20260902_120003") == {}
206 snapshot(elodin_dir,
"daq_20260902_120004", CONFIG_TOML)
209 {
"name":
"PT1.CH5.pressure_psi",
"entity":
"PT1.CH5"},
210 {
"name":
"CONTROLLER.state.to_state",
"entity":
"CONTROLLER.state"},
213 out = run_config.annotate(index,
"daq_20260902_120004")
214 assert out[
"components"][0][
"label"] ==
"Ox Upstream"
215 assert out[
"components"][1][
"label"] ==
""
216 assert out[
"has_config"]
is True
217 assert out[
"states"][
"16"] ==
"Burn"
218 assert "to_state" in out[
"state_fields"]
222 out = run_config.annotate({
"components": []},
"daq_20260101_000000")
223 assert out[
"has_config"]
is False
224 assert out[
"states"][
"16"] ==
"Fire"
234[sensor_roles_pt_board]
241[[boards.labjack_1.channels]]
246[[boards.labjack_1.channels]]
252[[boards.labjack_1.channels]]
260 snapshot(elodin_dir,
"daq_20261104_120000", T7_TOML)
261 labels = run_config.entity_labels(run_config.load(
"daq_20261104_120000"))
263 assert labels[
"T72.AIN1"] ==
"LOX Tank"
264 assert labels[
"T72_Cal.AIN1"] ==
"LOX Tank"
265 assert labels[
"T72_Cal.AIN2"] ==
"Nozzle TC"
267 assert labels[
"T72.AIN14"] ==
"LabJack T7 Board internal sensor"
268 assert labels[
"T72.CJC"] ==
"LabJack T7 Board cold junction"
270 assert "T72.AIN6" not in labels
271 assert labels[
"PT1.CH5"] ==
"Ox Upstream"
275 snapshot(elodin_dir,
"daq_20261104_120001", T7_TOML.replace(
'kind = "TC"',
'kind = "PT"'))
276 labels = run_config.entity_labels(run_config.load(
"daq_20261104_120001"))
277 assert "T72.CJC" not in labels
and "T72.AIN14" not in labels
test_t7_channels_take_their_role_raw_and_calibrated(elodin_dir)
elodin_dir(tmp_path, monkeypatch)
test_malformed_snapshot_does_not_raise(elodin_dir)
None snapshot(elodin_dir, str run_id, str text)
test_t7_without_a_thermocouple_names_no_cold_junction(elodin_dir)
test_slot_zero_means_ten()
test_states_fall_back_to_the_builtin_table_with_no_snapshot()
test_actuator_role_board_id_defaults_to_the_first_actuator_board(elodin_dir)
test_states_override_the_builtin_table_entry_by_entry(labels, elodin_dir)
test_self_test_entity_resolves_through_its_board(labels)
test_board_entities_are_keyed_by_board_id_not_slot(labels)
test_annotate_stamps_labels_and_state_metadata(elodin_dir)
test_ball_valve_role_names_its_own_entities(elodin_dir)
test_engine_state_is_not_a_state_field()
test_sensor_role_names_raw_and_calibrated(labels)
test_annotate_reports_a_run_with_no_snapshot(elodin_dir)
test_board_id_last_digit_is_the_elodin_slot(labels)
test_unnamed_entities_get_no_label(labels)
test_actuator_role_names_sense_and_command_entities(labels)
test_missing_snapshot_degrades_to_numbers(elodin_dir)
test_actuator_role_wins_over_a_sensor_role_on_the_same_channel(elodin_dir)