综合平台编程器项目的远程存储
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ů.
 
 
 
 

138 řádky
5.1 KiB

  1. #include "domain/project_storage.h"
  2. #include "domain/register_repository.h"
  3. #include "services/hmi_editor_service.h"
  4. #include "services/hmi_runtime_service.h"
  5. #include "services/project_service.h"
  6. #include <exception>
  7. #include <iostream>
  8. #include <stdexcept>
  9. #include <string>
  10. namespace {
  11. class TestProjectStorage final : public ProjectStorage
  12. {
  13. public:
  14. ProjectSaveResult save(const Project &, const std::string &) override
  15. {
  16. return {true, ProjectStorageError::None, {}};
  17. }
  18. ProjectLoadResult load(const std::string &) override
  19. {
  20. return {false, {}, ProjectStorageError::FileReadFailed, {}};
  21. }
  22. };
  23. void require(bool condition, const std::string &message)
  24. {
  25. if (!condition)
  26. {
  27. throw std::runtime_error(message);
  28. }
  29. }
  30. void testControlEditing()
  31. {
  32. TestProjectStorage storage;
  33. ProjectService project_service(storage);
  34. HmiEditorService service(project_service);
  35. const HmiEditorResult page_result = service.ensureDefaultPage();
  36. require(page_result.succeeded, "default HMI page creation must succeed");
  37. const std::string page_id = page_result.id;
  38. const HmiEditorResult button = service.addControl(page_id, HmiControlType::Button);
  39. const HmiEditorResult indicator = service.addControl(page_id, HmiControlType::Indicator);
  40. const HmiEditorResult display = service.addControl(
  41. page_id, HmiControlType::NumericDisplay);
  42. const HmiEditorResult input = service.addControl(page_id, HmiControlType::NumericInput);
  43. require(button.succeeded && indicator.succeeded && display.succeeded && input.succeeded,
  44. "four basic HMI controls must be added");
  45. const HmiPage *page = service.findPage(page_id);
  46. require(page != nullptr && page->controls.size() == 4,
  47. "all added controls must be kept in the page model");
  48. require(service.moveControl(page_id, button.id, {120, 80, 120, 40}).succeeded,
  49. "a valid control move must succeed");
  50. require(!service.moveControl(page_id, button.id, {790, 460, 120, 40}).succeeded,
  51. "a move outside the page must be rejected");
  52. HmiControl updated = *service.findControl(page_id, button.id);
  53. updated.binding = RegisterAddress{RegisterArea::D, 0};
  54. require(!service.updateControl(page_id, button.id, updated).succeeded,
  55. "buttons must reject D address bindings during editing");
  56. updated.binding = RegisterAddress{RegisterArea::M, 7};
  57. updated.text = "启动";
  58. require(service.updateControl(page_id, button.id, updated).succeeded,
  59. "a button M binding and edited text must be accepted");
  60. HmiControl duplicate = *service.findControl(page_id, indicator.id);
  61. duplicate.id = button.id;
  62. require(service.updateControl(page_id, indicator.id, duplicate).error
  63. == HmiEditorError::DuplicateId,
  64. "duplicate control ids must be rejected");
  65. require(service.removeControl(page_id, indicator.id).succeeded,
  66. "deleting a selected control must succeed");
  67. require(service.findControl(page_id, indicator.id) == nullptr,
  68. "deleted controls must not remain in the model");
  69. }
  70. void testRuntimeUsesRegisterRepository()
  71. {
  72. VirtualRegisterRepository repository;
  73. HmiRuntimeService runtime_service(repository);
  74. HmiControl button;
  75. button.id = "start";
  76. button.type = HmiControlType::Button;
  77. button.binding = RegisterAddress{RegisterArea::M, 12};
  78. require(runtime_service.toggleButton(button).succeeded,
  79. "button runtime writes must be accepted by the repository");
  80. require(repository.readBit(*button.binding).value,
  81. "button runtime writes must reach the M repository value");
  82. HmiControl indicator;
  83. indicator.id = "running";
  84. indicator.type = HmiControlType::Indicator;
  85. indicator.binding = RegisterAddress{RegisterArea::M, 12};
  86. const HmiRuntimeReadResult indicator_value = runtime_service.readControl(indicator);
  87. require(indicator_value.succeeded && indicator_value.bit_value,
  88. "indicators must read M values through the repository");
  89. HmiControl numeric_input;
  90. numeric_input.id = "target";
  91. numeric_input.type = HmiControlType::NumericInput;
  92. numeric_input.binding = RegisterAddress{RegisterArea::D, 9};
  93. require(runtime_service.writeNumericInput(numeric_input, -18).succeeded,
  94. "numeric input runtime writes must be accepted by the repository");
  95. HmiControl numeric_display;
  96. numeric_display.id = "actual";
  97. numeric_display.type = HmiControlType::NumericDisplay;
  98. numeric_display.binding = RegisterAddress{RegisterArea::D, 9};
  99. const HmiRuntimeReadResult numeric_value = runtime_service.readControl(numeric_display);
  100. require(numeric_value.succeeded && numeric_value.word_value == -18,
  101. "numeric display must read D values through the repository");
  102. }
  103. } // namespace
  104. int main()
  105. {
  106. try
  107. {
  108. testControlEditing();
  109. testRuntimeUsesRegisterRepository();
  110. }
  111. catch (const std::exception &error)
  112. {
  113. std::cerr << "HMI editor service tests failed: " << error.what() << '\n';
  114. return 1;
  115. }
  116. std::cout << "HMI editor service tests passed\n";
  117. return 0;
  118. }