test_skip_objects_confirmation_g7.py 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. """Skipping objects is confirmed by the printer, or the log says it was not.
  2. skip_objects marked the objects skipped as soon as the command was published
  3. and never read the answer. Only the printer's own s_obj list corrected that,
  4. and nothing recorded a skip the printer refused or never applied.
  5. """
  6. import logging
  7. from unittest.mock import MagicMock, patch
  8. import pytest
  9. from backend.app.services import bambu_mqtt
  10. from backend.app.services.bambu_mqtt import BambuMQTTClient
  11. @pytest.fixture
  12. def client():
  13. c = BambuMQTTClient(ip_address="10.0.0.9", serial_number="SN-SKIP", access_code="x", model="X1C")
  14. c._client = MagicMock()
  15. c.state.connected = True
  16. c.state.state = "RUNNING"
  17. return c
  18. def _sent_seq(c) -> str:
  19. import json
  20. return json.loads(c._client.publish.call_args.args[1])["print"]["sequence_id"]
  21. def test_a_refusal_is_logged_and_undone(client, caplog):
  22. assert client.skip_objects([5, 6])
  23. seq = _sent_seq(client)
  24. with caplog.at_level(logging.ERROR):
  25. client._process_message(
  26. {"print": {"command": "skip_objects", "sequence_id": seq, "result": "fail", "reason": "busy"}}
  27. )
  28. assert client.state.skipped_objects == []
  29. assert any("refused" in r.message and "busy" in r.message for r in caplog.records)
  30. def test_the_printers_list_confirms_it(client, caplog):
  31. with patch.object(bambu_mqtt.time, "monotonic", return_value=1_000.0):
  32. client.skip_objects([5])
  33. client._process_message({"print": {"command": "push_status", "s_obj": [5]}})
  34. with (
  35. patch.object(bambu_mqtt.time, "monotonic", return_value=1_000.0 + bambu_mqtt.SKIP_CONFIRM_TIMEOUT_S + 1),
  36. caplog.at_level(logging.ERROR),
  37. ):
  38. client._process_message({"print": {"command": "push_status", "mc_percent": 50}})
  39. assert not [r for r in caplog.records if r.levelno >= logging.ERROR]
  40. def test_no_confirmation_is_logged_once(client, caplog):
  41. with patch.object(bambu_mqtt.time, "monotonic", return_value=1_000.0):
  42. client.skip_objects([7])
  43. with (
  44. patch.object(bambu_mqtt.time, "monotonic", return_value=1_000.0 + bambu_mqtt.SKIP_CONFIRM_TIMEOUT_S + 1),
  45. caplog.at_level(logging.ERROR),
  46. ):
  47. client._process_message({"print": {"command": "push_status", "mc_percent": 50}})
  48. client._process_message({"print": {"command": "push_status", "mc_percent": 51}})
  49. errors = [r for r in caplog.records if r.levelno >= logging.ERROR]
  50. assert len(errors) == 1 and "did not confirm" in errors[0].message
  51. def test_a_print_that_ends_first_logs_nothing(client, caplog):
  52. with patch.object(bambu_mqtt.time, "monotonic", return_value=1_000.0):
  53. client.skip_objects([7])
  54. client._process_message({"print": {"command": "push_status", "gcode_state": "FINISH"}})
  55. with (
  56. patch.object(bambu_mqtt.time, "monotonic", return_value=1_000.0 + bambu_mqtt.SKIP_CONFIRM_TIMEOUT_S + 1),
  57. caplog.at_level(logging.ERROR),
  58. ):
  59. client._process_message({"print": {"command": "push_status", "mc_percent": 0}})
  60. assert not [r for r in caplog.records if "confirm" in r.message]