test_value_refresh.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import logging
  2. import unittest
  3. from point_model import ModbusPoint
  4. from register_store import RegisterStore, initialize_register_store
  5. from value_provider import ValueProvider
  6. from value_refresh import ValueRefreshWorker
  7. class FakeProvider(ValueProvider):
  8. def __init__(self, values):
  9. self.values = values
  10. def fetch_values(self, point_ids):
  11. return {point_id: self.values[point_id] for point_id in point_ids if point_id in self.values}
  12. class FailingProvider(ValueProvider):
  13. def fetch_values(self, point_ids):
  14. raise RuntimeError("boom")
  15. class FailingMiddleBatchProvider(ValueProvider):
  16. def __init__(self):
  17. self.called_batches = []
  18. def fetch_values(self, point_ids):
  19. self.called_batches.append(point_ids)
  20. if point_ids[0] == "p200":
  21. raise RuntimeError("boom")
  22. return {point_id: int(point_id[1:]) for point_id in point_ids}
  23. class ValueRefreshTest(unittest.TestCase):
  24. def setUp(self):
  25. logging.disable(logging.CRITICAL)
  26. def tearDown(self):
  27. logging.disable(logging.NOTSET)
  28. def test_initial_missing_value_raises(self):
  29. points = [
  30. ModbusPoint("a", "A", "int16", 1, 0),
  31. ModbusPoint("b", "B", "int16", 1, 1),
  32. ]
  33. store = RegisterStore()
  34. initialize_register_store(points, store)
  35. worker = ValueRefreshWorker(points, FakeProvider({"a": 12}), store, 5)
  36. with self.assertRaises(RuntimeError):
  37. worker.refresh_once(initial=True)
  38. self.assertEqual(store.read_holding_registers(1, 0, 2), [12, 0])
  39. def test_periodic_missing_value_keeps_old_value(self):
  40. points = [ModbusPoint("a", "A", "int16", 1, 0)]
  41. store = RegisterStore()
  42. initialize_register_store(points, store)
  43. ValueRefreshWorker(points, FakeProvider({"a": 5}), store, 5).refresh_once(initial=True)
  44. ValueRefreshWorker(points, FakeProvider({}), store, 5).refresh_once(initial=False)
  45. self.assertEqual(store.read_holding_registers(1, 0, 1), [5])
  46. def test_initial_provider_failure_raises(self):
  47. points = [ModbusPoint("a", "A", "int16", 1, 0)]
  48. store = RegisterStore()
  49. initialize_register_store(points, store)
  50. with self.assertRaises(RuntimeError):
  51. ValueRefreshWorker(points, FailingProvider(), store, 5).refresh_once(initial=True)
  52. self.assertEqual(store.read_holding_registers(1, 0, 1), [0])
  53. def test_periodic_provider_failure_continues_next_batch(self):
  54. points = [ModbusPoint(f"p{i}", f"P{i}", "int16", 1, i) for i in range(401)]
  55. store = RegisterStore()
  56. initialize_register_store(points, store)
  57. provider = FailingMiddleBatchProvider()
  58. ValueRefreshWorker(points, provider, store, 5).refresh_once(initial=False)
  59. self.assertEqual(len(provider.called_batches), 3)
  60. self.assertEqual(store.read_holding_registers(1, 0, 1), [0])
  61. self.assertEqual(store.read_holding_registers(1, 199, 3), [199, 0, 0])
  62. self.assertEqual(store.read_holding_registers(1, 400, 1), [400])
  63. if __name__ == "__main__":
  64. unittest.main()