综合平台编程器项目的远程存储
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

145 рядки
5.1 KiB

  1. #include "domain/project_storage.h"
  2. #include "services/logic_editor_service.h"
  3. #include "services/project_service.h"
  4. #include <exception>
  5. #include <iostream>
  6. #include <stdexcept>
  7. namespace {
  8. class TestProjectStorage final : public ProjectStorage
  9. {
  10. public:
  11. ProjectSaveResult save(const Project &, const std::string &) override
  12. {
  13. return {true, ProjectStorageError::None, {}};
  14. }
  15. ProjectLoadResult load(const std::string &) override
  16. {
  17. return {false, {}, ProjectStorageError::FileReadFailed, {}};
  18. }
  19. };
  20. void require(bool condition, const std::string &message)
  21. {
  22. if (!condition)
  23. {
  24. throw std::runtime_error(message);
  25. }
  26. }
  27. void testEditorOperations()
  28. {
  29. TestProjectStorage storage;
  30. ProjectService project_service(storage);
  31. LogicEditorService service(project_service);
  32. const LogicEditorResult logic_result = service.ensureDefaultLogic();
  33. require(logic_result.succeeded, "default logic must be created");
  34. const std::string logic_id = logic_result.id;
  35. const std::string rung_id = service.firstRungId(logic_id);
  36. require(!rung_id.empty(), "default logic must contain an editable rung");
  37. const LogicEditorResult stop_result = service.appendCondition(
  38. logic_id,
  39. rung_id,
  40. ContactNodeConfig{
  41. RegisterAddress{RegisterArea::M, 1},
  42. ContactMode::NormallyClosed});
  43. const LogicEditorResult start_result = service.appendCondition(
  44. logic_id,
  45. rung_id,
  46. ContactNodeConfig{
  47. RegisterAddress{RegisterArea::M, 0},
  48. ContactMode::NormallyOpen});
  49. require(stop_result.succeeded && start_result.succeeded,
  50. "series contacts must be appended as ladder stages");
  51. const std::string start_stage_id = service.stageIdForNode(
  52. logic_id, start_result.id);
  53. const LogicEditorResult hold_result = service.addParallelCondition(
  54. logic_id,
  55. rung_id,
  56. start_stage_id,
  57. ContactNodeConfig{
  58. RegisterAddress{RegisterArea::M, 2},
  59. ContactMode::NormallyOpen});
  60. const LogicEditorResult coil_result = service.setOutput(
  61. logic_id,
  62. rung_id,
  63. CoilNodeConfig{
  64. RegisterAddress{RegisterArea::M, 2},
  65. CoilMode::Normal});
  66. require(hold_result.succeeded && coil_result.succeeded,
  67. "parallel hold contact and output coil must be added");
  68. require(!service.findNode(logic_id, stop_result.id)->configured,
  69. "new logic nodes must remain unconfigured until properties are applied");
  70. require(service.updateNodeConfig(
  71. logic_id,
  72. stop_result.id,
  73. ContactNodeConfig{
  74. RegisterAddress{RegisterArea::M, 1},
  75. ContactMode::NormallyClosed})
  76. .succeeded,
  77. "applying logic node properties must succeed");
  78. require(service.findNode(logic_id, stop_result.id)->configured,
  79. "applying logic node properties must mark the node configured");
  80. const LadderRung *rung = service.findRung(logic_id, rung_id);
  81. require(rung != nullptr && rung->stages.size() == 2,
  82. "series conditions must occupy ordered stages");
  83. require(rung->stages.at(1).branches.size() == 2,
  84. "parallel conditions must share one stage");
  85. require(rung->output.has_value(), "rung output must be fixed separately");
  86. require(service.findLogic(logic_id)->validate(),
  87. "configured self-hold ladder must pass full validation");
  88. const LogicNode *start = service.findNode(logic_id, start_result.id);
  89. require(start != nullptr, "added condition must be discoverable");
  90. require(service.updateNodeConfig(
  91. logic_id,
  92. start_result.id,
  93. ContactNodeConfig{
  94. RegisterAddress{RegisterArea::M, 2},
  95. ContactMode::NormallyClosed})
  96. .succeeded,
  97. "contact properties must be editable");
  98. require(service.removeNode(logic_id, hold_result.id).succeeded,
  99. "parallel branch deletion must succeed");
  100. require(service.findRung(logic_id, rung_id)->stages.at(1).branches.size() == 1,
  101. "deleting one branch must keep the ladder stage");
  102. require(service.removeNode(logic_id, start_result.id).succeeded,
  103. "last branch deletion must succeed");
  104. require(service.findRung(logic_id, rung_id)->stages.size() == 1,
  105. "deleting the last branch must remove the empty stage");
  106. const LogicEditorResult second_rung = service.addRung(logic_id);
  107. require(second_rung.succeeded, "additional ladder rungs must be supported");
  108. require(service.removeRung(logic_id, second_rung.id).succeeded,
  109. "additional ladder rungs must be removable");
  110. require(!service.removeRung(logic_id, rung_id).succeeded,
  111. "the only remaining ladder rung must not be removed");
  112. }
  113. } // namespace
  114. int main()
  115. {
  116. try
  117. {
  118. testEditorOperations();
  119. }
  120. catch (const std::exception &error)
  121. {
  122. std::cerr << "logic editor service tests failed: " << error.what() << '\n';
  123. return 1;
  124. }
  125. std::cout << "logic editor service tests passed\n";
  126. return 0;
  127. }