test_printer_kill_switch.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. from types import SimpleNamespace
  2. import pytest
  3. from backend.app import main as main_module
  4. @pytest.fixture(autouse=True)
  5. def clear_kill_switch_state():
  6. main_module._unauthorized_print_kill_sent.clear()
  7. main_module._expected_prints.clear()
  8. main_module._active_prints.clear()
  9. main_module._expected_print_registered_at.clear()
  10. yield
  11. main_module._unauthorized_print_kill_sent.clear()
  12. main_module._expected_prints.clear()
  13. main_module._active_prints.clear()
  14. main_module._expected_print_registered_at.clear()
  15. def test_gcode_3mf_status_filename_matches_registered_expected_print():
  16. state = SimpleNamespace(
  17. current_print=None,
  18. subtask_name="",
  19. gcode_file="foreign_job.gcode.3mf",
  20. )
  21. keys = main_module._build_status_print_keys(7, state)
  22. assert (7, "foreign_job.gcode.3mf") in keys
  23. assert (7, "foreign_job.gcode") in keys
  24. @pytest.mark.asyncio
  25. async def test_unauthorized_active_print_triggers_stop(monkeypatch):
  26. stop_calls: list[int] = []
  27. async def fake_status(*args, **kwargs):
  28. return None
  29. async def kill_switch_enabled(_db):
  30. return True
  31. monkeypatch.setattr(main_module.printer_manager, "get_current_print_user", lambda printer_id: None)
  32. monkeypatch.setattr(
  33. main_module.printer_manager, "stop_print", lambda printer_id: stop_calls.append(printer_id) or True
  34. )
  35. monkeypatch.setattr(main_module.printer_manager, "get_printer", lambda printer_id: None)
  36. monkeypatch.setattr(main_module.printer_manager, "get_model", lambda printer_id: None)
  37. monkeypatch.setattr(main_module, "printer_state_to_dict", lambda *args, **kwargs: {})
  38. monkeypatch.setattr(main_module.mqtt_relay, "on_printer_status", fake_status)
  39. monkeypatch.setattr(main_module.ws_manager, "send_printer_status", fake_status)
  40. monkeypatch.setattr("backend.app.services.finance_budget.is_printer_kill_switch_enabled", kill_switch_enabled)
  41. state = SimpleNamespace(
  42. connected=True,
  43. state="RUNNING",
  44. progress=0,
  45. remaining_time=0,
  46. layer_num=0,
  47. temperatures={},
  48. raw_data={},
  49. stg_cur=0,
  50. cooling_fan_speed=None,
  51. big_fan1_speed=None,
  52. big_fan2_speed=None,
  53. chamber_light=False,
  54. active_extruder=0,
  55. tray_now=255,
  56. door_open=False,
  57. ams_filament_backup=False,
  58. current_print=None,
  59. subtask_name="foreign_job",
  60. gcode_file="foreign_job.gcode",
  61. )
  62. await main_module.on_printer_status_change(7, state)
  63. assert stop_calls == [7]
  64. assert 7 in main_module._unauthorized_print_kill_sent
  65. @pytest.mark.asyncio
  66. async def test_bambuddy_authorized_print_is_not_stopped(monkeypatch):
  67. monkeypatch.setitem(main_module._expected_prints, (7, "foreign_job"), 123)
  68. stop_calls: list[int] = []
  69. async def fake_status(*args, **kwargs):
  70. return None
  71. async def kill_switch_enabled(_db):
  72. return True
  73. monkeypatch.setattr(main_module.printer_manager, "get_current_print_user", lambda printer_id: None)
  74. monkeypatch.setattr(
  75. main_module.printer_manager, "stop_print", lambda printer_id: stop_calls.append(printer_id) or True
  76. )
  77. monkeypatch.setattr(main_module.printer_manager, "get_printer", lambda printer_id: None)
  78. monkeypatch.setattr(main_module.printer_manager, "get_model", lambda printer_id: None)
  79. monkeypatch.setattr(main_module, "printer_state_to_dict", lambda *args, **kwargs: {})
  80. monkeypatch.setattr(main_module.mqtt_relay, "on_printer_status", fake_status)
  81. monkeypatch.setattr(main_module.ws_manager, "send_printer_status", fake_status)
  82. monkeypatch.setattr("backend.app.services.finance_budget.is_printer_kill_switch_enabled", kill_switch_enabled)
  83. state = SimpleNamespace(
  84. connected=True,
  85. state="RUNNING",
  86. progress=0,
  87. remaining_time=0,
  88. layer_num=0,
  89. temperatures={},
  90. raw_data={},
  91. stg_cur=0,
  92. cooling_fan_speed=None,
  93. big_fan1_speed=None,
  94. big_fan2_speed=None,
  95. chamber_light=False,
  96. active_extruder=0,
  97. tray_now=255,
  98. door_open=False,
  99. ams_filament_backup=False,
  100. current_print=None,
  101. subtask_name="foreign_job",
  102. gcode_file="foreign_job.gcode",
  103. )
  104. await main_module.on_printer_status_change(7, state)
  105. assert stop_calls == []
  106. assert 7 not in main_module._unauthorized_print_kill_sent
  107. @pytest.mark.asyncio
  108. async def test_unauthorized_print_state_is_cleared_when_print_ends(monkeypatch):
  109. stop_calls: list[int] = []
  110. async def fake_status(*args, **kwargs):
  111. return None
  112. async def kill_switch_enabled(_db):
  113. return True
  114. monkeypatch.setattr(main_module.printer_manager, "get_current_print_user", lambda printer_id: None)
  115. monkeypatch.setattr(
  116. main_module.printer_manager, "stop_print", lambda printer_id: stop_calls.append(printer_id) or True
  117. )
  118. monkeypatch.setattr(main_module.printer_manager, "get_printer", lambda printer_id: None)
  119. monkeypatch.setattr(main_module.printer_manager, "get_model", lambda printer_id: None)
  120. monkeypatch.setattr(main_module, "printer_state_to_dict", lambda *args, **kwargs: {})
  121. monkeypatch.setattr(main_module.mqtt_relay, "on_printer_status", fake_status)
  122. monkeypatch.setattr(main_module.ws_manager, "send_printer_status", fake_status)
  123. monkeypatch.setattr("backend.app.services.finance_budget.is_printer_kill_switch_enabled", kill_switch_enabled)
  124. active_state = SimpleNamespace(
  125. connected=True,
  126. state="RUNNING",
  127. progress=0,
  128. remaining_time=0,
  129. layer_num=0,
  130. temperatures={},
  131. raw_data={},
  132. stg_cur=0,
  133. cooling_fan_speed=None,
  134. big_fan1_speed=None,
  135. big_fan2_speed=None,
  136. chamber_light=False,
  137. active_extruder=0,
  138. tray_now=255,
  139. door_open=False,
  140. ams_filament_backup=False,
  141. current_print=None,
  142. subtask_name="foreign_job",
  143. gcode_file="foreign_job.gcode",
  144. )
  145. idle_state = SimpleNamespace(
  146. connected=True,
  147. state="IDLE",
  148. progress=0,
  149. remaining_time=0,
  150. layer_num=0,
  151. temperatures={},
  152. raw_data={},
  153. stg_cur=0,
  154. cooling_fan_speed=None,
  155. big_fan1_speed=None,
  156. big_fan2_speed=None,
  157. chamber_light=False,
  158. active_extruder=0,
  159. tray_now=255,
  160. door_open=False,
  161. ams_filament_backup=False,
  162. current_print=None,
  163. subtask_name="",
  164. gcode_file=None,
  165. )
  166. await main_module.on_printer_status_change(7, active_state)
  167. assert stop_calls == [7]
  168. assert 7 in main_module._unauthorized_print_kill_sent
  169. await main_module.on_printer_status_change(7, idle_state)
  170. assert 7 not in main_module._unauthorized_print_kill_sent