test_bambu_mqtt_cfg_parse.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. """Tests for ``parse_ams_filament_backup_from_cfg`` (#1766 prefer_lowest gate).
  2. The function extracts bit 18 of Bambu's top-level ``print.cfg`` hex string,
  3. which OrcaSlicer's DeviceManager.cpp:4961 maps to AMS Filament Backup. These
  4. tests pin the bit position + cover the absent / malformed cases A1-family
  5. printers and pre-init pushes produce.
  6. """
  7. import pytest
  8. from backend.app.services.bambu_mqtt import (
  9. parse_ams_filament_backup_from_cfg,
  10. parse_ams_filament_backup_from_home_flag,
  11. )
  12. class TestParseAmsFilamentBackupFromCfg:
  13. def test_h2d_on_capture(self):
  14. # Captured 2026-06-20 from H2D fw 01.03.00.00 with backup ON.
  15. # Hex "C0340FC219" has bit 18 set (nibble 5 = F = 0b1111).
  16. assert parse_ams_filament_backup_from_cfg("C0340FC219") is True
  17. def test_h2d_off_capture(self):
  18. # Same printer, backup toggled OFF — only bit 18 flips:
  19. # "C0340BC219" — nibble 5 = B = 0b1011.
  20. assert parse_ams_filament_backup_from_cfg("C0340BC219") is False
  21. def test_x1c_short_hex_string_on(self):
  22. # X1C cfg in the investigation snapshots is short ("FCA09").
  23. # Bit 18 of 0xFCA09 = 0b1111110010100001001, bit18 set.
  24. assert parse_ams_filament_backup_from_cfg("FCA09") is True
  25. def test_lowercase_hex(self):
  26. # Robustness: int(s, 16) accepts both cases; check we don't regress.
  27. assert parse_ams_filament_backup_from_cfg("c0340fc219") is True
  28. def test_only_bit_18_isolated(self):
  29. # Sanity: a value with ONLY bit 18 set must parse as True.
  30. assert parse_ams_filament_backup_from_cfg(hex(1 << 18)[2:]) is True
  31. def test_bit_18_clear_but_others_set(self):
  32. # Set every bit EXCEPT 18 — must parse as False.
  33. mask = (~(1 << 18)) & 0xFFFFFFFF
  34. assert parse_ams_filament_backup_from_cfg(hex(mask)[2:]) is False
  35. @pytest.mark.parametrize(
  36. "value",
  37. [
  38. None, # field omitted (A1 family old protocol)
  39. "", # empty string
  40. 123, # firmware-emitted int instead of hex string (defensive)
  41. "not_hex", # malformed
  42. "0xZZ", # invalid hex
  43. ["FCA09"], # wrong shape
  44. {"cfg": "FCA09"}, # nested by mistake
  45. ],
  46. )
  47. def test_invalid_returns_none(self, value):
  48. # None preserves today's behaviour for callers gating on backup state —
  49. # NOT False. Treating absent as OFF would regress A1-family scheduling.
  50. assert parse_ams_filament_backup_from_cfg(value) is None
  51. class TestParseAmsFilamentBackupFromHomeFlag:
  52. """``home_flag`` bit 10, the only source on families without ``cfg``
  53. (#3259). Values are from support-bundle push_status snapshots."""
  54. def test_p1s_on(self):
  55. # P1S fw 01.10.00.00 full status: no cfg, home_flag bit 10 set.
  56. assert parse_ams_filament_backup_from_home_flag(7554719) is True
  57. def test_a1_off(self):
  58. # A1 fw 01.08.01.00: home_flag bit 10 clear.
  59. assert parse_ams_filament_backup_from_home_flag(846152095) is False
  60. def test_negative_value(self):
  61. # X1-class firmware sends the 32-bit flag as a signed int; its bit 10
  62. # matches cfg bit 18 in the same frames (ON and OFF).
  63. assert parse_ams_filament_backup_from_home_flag(-1067070056) is True
  64. assert parse_ams_filament_backup_from_home_flag(-1067069137) is False
  65. @pytest.mark.parametrize("value", [None, "1024", True, 10.0, [1024]])
  66. def test_invalid_returns_none(self, value):
  67. assert parse_ams_filament_backup_from_home_flag(value) is None