test_printer_kill_switch.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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 state, printer_id, model: {})
  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. layer_num=0,
  46. temperatures={},
  47. raw_data={},
  48. stg_cur=0,
  49. cooling_fan_speed=None,
  50. big_fan1_speed=None,
  51. big_fan2_speed=None,
  52. chamber_light=False,
  53. active_extruder=0,
  54. tray_now=255,
  55. door_open=False,
  56. current_print=None,
  57. subtask_name="foreign_job",
  58. gcode_file="foreign_job.gcode",
  59. )
  60. await main_module.on_printer_status_change(7, state)
  61. assert stop_calls == [7]
  62. assert 7 in main_module._unauthorized_print_kill_sent
  63. @pytest.mark.asyncio
  64. async def test_bambuddy_authorized_print_is_not_stopped(monkeypatch):
  65. monkeypatch.setitem(main_module._expected_prints, (7, "foreign_job"), 123)
  66. stop_calls: list[int] = []
  67. async def fake_status(*args, **kwargs):
  68. return None
  69. async def kill_switch_enabled(_db):
  70. return True
  71. monkeypatch.setattr(main_module.printer_manager, "get_current_print_user", lambda printer_id: None)
  72. monkeypatch.setattr(
  73. main_module.printer_manager, "stop_print", lambda printer_id: stop_calls.append(printer_id) or True
  74. )
  75. monkeypatch.setattr(main_module.printer_manager, "get_printer", lambda printer_id: None)
  76. monkeypatch.setattr(main_module.printer_manager, "get_model", lambda printer_id: None)
  77. monkeypatch.setattr(main_module, "printer_state_to_dict", lambda state, printer_id, model: {})
  78. monkeypatch.setattr(main_module.mqtt_relay, "on_printer_status", fake_status)
  79. monkeypatch.setattr(main_module.ws_manager, "send_printer_status", fake_status)
  80. monkeypatch.setattr("backend.app.services.finance_budget.is_printer_kill_switch_enabled", kill_switch_enabled)
  81. state = SimpleNamespace(
  82. connected=True,
  83. state="RUNNING",
  84. progress=0,
  85. layer_num=0,
  86. temperatures={},
  87. raw_data={},
  88. stg_cur=0,
  89. cooling_fan_speed=None,
  90. big_fan1_speed=None,
  91. big_fan2_speed=None,
  92. chamber_light=False,
  93. active_extruder=0,
  94. tray_now=255,
  95. door_open=False,
  96. current_print=None,
  97. subtask_name="foreign_job",
  98. gcode_file="foreign_job.gcode",
  99. )
  100. await main_module.on_printer_status_change(7, state)
  101. assert stop_calls == []
  102. assert 7 not in main_module._unauthorized_print_kill_sent
  103. @pytest.mark.asyncio
  104. async def test_unauthorized_print_state_is_cleared_when_print_ends(monkeypatch):
  105. stop_calls: list[int] = []
  106. async def fake_status(*args, **kwargs):
  107. return None
  108. async def kill_switch_enabled(_db):
  109. return True
  110. monkeypatch.setattr(main_module.printer_manager, "get_current_print_user", lambda printer_id: None)
  111. monkeypatch.setattr(
  112. main_module.printer_manager, "stop_print", lambda printer_id: stop_calls.append(printer_id) or True
  113. )
  114. monkeypatch.setattr(main_module.printer_manager, "get_printer", lambda printer_id: None)
  115. monkeypatch.setattr(main_module.printer_manager, "get_model", lambda printer_id: None)
  116. monkeypatch.setattr(main_module, "printer_state_to_dict", lambda state, printer_id, model: {})
  117. monkeypatch.setattr(main_module.mqtt_relay, "on_printer_status", fake_status)
  118. monkeypatch.setattr(main_module.ws_manager, "send_printer_status", fake_status)
  119. monkeypatch.setattr("backend.app.services.finance_budget.is_printer_kill_switch_enabled", kill_switch_enabled)
  120. active_state = SimpleNamespace(
  121. connected=True,
  122. state="RUNNING",
  123. progress=0,
  124. layer_num=0,
  125. temperatures={},
  126. raw_data={},
  127. stg_cur=0,
  128. cooling_fan_speed=None,
  129. big_fan1_speed=None,
  130. big_fan2_speed=None,
  131. chamber_light=False,
  132. active_extruder=0,
  133. tray_now=255,
  134. door_open=False,
  135. current_print=None,
  136. subtask_name="foreign_job",
  137. gcode_file="foreign_job.gcode",
  138. )
  139. idle_state = SimpleNamespace(
  140. connected=True,
  141. state="IDLE",
  142. progress=0,
  143. layer_num=0,
  144. temperatures={},
  145. raw_data={},
  146. stg_cur=0,
  147. cooling_fan_speed=None,
  148. big_fan1_speed=None,
  149. big_fan2_speed=None,
  150. chamber_light=False,
  151. active_extruder=0,
  152. tray_now=255,
  153. door_open=False,
  154. current_print=None,
  155. subtask_name="",
  156. gcode_file=None,
  157. )
  158. await main_module.on_printer_status_change(7, active_state)
  159. assert stop_calls == [7]
  160. assert 7 in main_module._unauthorized_print_kill_sent
  161. await main_module.on_printer_status_change(7, idle_state)
  162. assert 7 not in main_module._unauthorized_print_kill_sent