综合平台编程器项目的远程存储
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 

122 řádky
5.1 KiB

  1. #include "domain/active_register_repository.h"
  2. #include "domain/register_monitor_model.h"
  3. #include "domain/register_repository.h"
  4. #include "domain/virtual_register_repository.h"
  5. #include "services/register_monitor_service.h"
  6. #include "support/test_support.h"
  7. #include <iostream>
  8. #include <stdexcept>
  9. #include <string>
  10. namespace {
  11. using TestSupport::require;
  12. void testRangeManagement()
  13. {
  14. VirtualRegisterRepository repository;
  15. RegisterMonitorService service(repository);
  16. int change_count = 0;
  17. service.setAddressesChangedCallback([&change_count] { ++change_count; });
  18. const RegisterMonitorResult added = service.addRange(" d10 ", 3);
  19. require(added.succeeded && added.affectedCount == 3
  20. && service.addresses().size() == 3U,
  21. "monitor service must expand a normalized continuous address range");
  22. require(service.addresses().front() == RegisterAddress{RegisterArea::D, 10}
  23. && service.addresses().back() == RegisterAddress{RegisterArea::D, 12},
  24. "monitor service must preserve expanded address order");
  25. const RegisterMonitorResult duplicate = service.addRange("D11", 2);
  26. require(!duplicate.succeeded && duplicate.error == RegisterMonitorError::NoChange,
  27. "monitor service must reject a fully duplicated range");
  28. require(!service.addRange("M4000", 2).succeeded,
  29. "monitor service must reject a range crossing address 4000");
  30. require(change_count == 1,
  31. "failed additions must not report a monitor address change");
  32. require(service.remove({RegisterAddress{RegisterArea::D, 11}}).succeeded
  33. && service.addresses().size() == 2U,
  34. "monitor service must remove selected addresses");
  35. require(service.clear().succeeded && service.addresses().empty(),
  36. "monitor service must clear the current monitor table");
  37. require(change_count == 3,
  38. "successful add, remove and clear operations must notify address changes");
  39. }
  40. void testSharedActiveRepositoryValues()
  41. {
  42. VirtualRegisterRepository virtual_repository;
  43. VirtualRegisterRepository plc_repository;
  44. ActiveRegisterRepository active_repository(virtual_repository);
  45. RegisterMonitorService service(active_repository);
  46. require(service.addRange("M0", 1).succeeded
  47. && service.addRange("D0", 1).succeeded,
  48. "monitor service must accept one M and one D address");
  49. virtual_repository.writeBit({RegisterArea::M, 0}, true);
  50. virtual_repository.writeWord({RegisterArea::D, 0}, -123);
  51. std::vector<MonitorValue> values = service.values(false);
  52. require(values.size() == 2U && values[0].bitValue && values[1].wordValue == -123,
  53. "monitor values must reflect the active virtual repository");
  54. plc_repository.writeBit({RegisterArea::M, 0}, false);
  55. plc_repository.writeWord({RegisterArea::D, 0}, 456);
  56. active_repository.use(plc_repository);
  57. values = service.values(false);
  58. require(!values[0].bitValue && values[1].wordValue == 456,
  59. "monitor values must follow the active repository switch");
  60. values = service.values(true);
  61. require(values[0].state == MonitorValueState::CommunicationFault
  62. && values[1].state == MonitorValueState::CommunicationFault,
  63. "valid cached values must be marked stale during a communication fault");
  64. }
  65. void testRegisterWrites()
  66. {
  67. VirtualRegisterRepository repository;
  68. RegisterMonitorService service(repository);
  69. const RegisterAddress m0{RegisterArea::M, 0};
  70. const RegisterAddress d0{RegisterArea::D, 0};
  71. const RegisterMonitorWriteResult bit_write = service.writeBit(m0, true);
  72. require(bit_write.succeeded && repository.readBit(m0).value,
  73. "monitor service must write M values through the active repository");
  74. const RegisterMonitorWriteResult word_write = service.writeWord(d0, -123);
  75. require(word_write.succeeded && repository.readWord(d0).value == -123,
  76. "monitor service must write signed D values through the active repository");
  77. const RegisterMonitorWriteResult wrong_bit = service.writeBit(d0, true);
  78. require(!wrong_bit.succeeded && wrong_bit.error == RegisterError::AreaMismatch,
  79. "monitor bit writes must reject D addresses");
  80. const RegisterMonitorWriteResult wrong_word = service.writeWord(m0, 123);
  81. require(!wrong_word.succeeded && wrong_word.error == RegisterError::AreaMismatch,
  82. "monitor word writes must reject M addresses");
  83. require(service.writeWord(d0, static_cast<std::int16_t>(-32768)).succeeded
  84. && repository.readWord(d0).value == -32768
  85. && service.writeWord(d0, static_cast<std::int16_t>(32767)).succeeded
  86. && repository.readWord(d0).value == 32767,
  87. "monitor word writes must preserve signed 16-bit boundary values");
  88. }
  89. } // namespace
  90. int main()
  91. {
  92. try
  93. {
  94. testRangeManagement();
  95. testSharedActiveRepositoryValues();
  96. testRegisterWrites();
  97. }
  98. catch (const std::exception &error)
  99. {
  100. std::cerr << "register monitor service tests failed: " << error.what() << '\n';
  101. return 1;
  102. }
  103. std::cout << "register monitor service tests passed\n";
  104. return 0;
  105. }