|
- #include "domain/project_storage.h"
- #include "services/logic_editor_service.h"
- #include "services/project_service.h"
-
- #include <exception>
- #include <iostream>
- #include <stdexcept>
-
- namespace {
-
- class TestProjectStorage final : public ProjectStorage
- {
- public:
- ProjectSaveResult save(const Project &, const std::string &) override
- {
- return {true, ProjectStorageError::None, {}};
- }
-
- ProjectLoadResult load(const std::string &) override
- {
- return {false, {}, ProjectStorageError::FileReadFailed, {}};
- }
- };
-
- void require(bool condition, const std::string &message)
- {
- if (!condition)
- {
- throw std::runtime_error(message);
- }
- }
-
- void testEditorOperations()
- {
- TestProjectStorage storage;
- ProjectService project_service(storage);
- LogicEditorService service(project_service);
- const LogicEditorResult logic_result = service.ensureDefaultLogic();
- require(logic_result.succeeded, "default logic must be created");
- const std::string logic_id = logic_result.id;
-
- const std::string rung_id = service.firstRungId(logic_id);
- require(!rung_id.empty(), "default logic must contain an editable rung");
-
- const LogicEditorResult stop_result = service.appendCondition(
- logic_id,
- rung_id,
- ContactNodeConfig{
- RegisterAddress{RegisterArea::M, 1},
- ContactMode::NormallyClosed});
- const LogicEditorResult start_result = service.appendCondition(
- logic_id,
- rung_id,
- ContactNodeConfig{
- RegisterAddress{RegisterArea::M, 0},
- ContactMode::NormallyOpen});
- require(stop_result.succeeded && start_result.succeeded,
- "series contacts must be appended as ladder stages");
-
- const std::string start_stage_id = service.stageIdForNode(
- logic_id, start_result.id);
- const LogicEditorResult hold_result = service.addParallelCondition(
- logic_id,
- rung_id,
- start_stage_id,
- ContactNodeConfig{
- RegisterAddress{RegisterArea::M, 2},
- ContactMode::NormallyOpen});
- const LogicEditorResult coil_result = service.setOutput(
- logic_id,
- rung_id,
- CoilNodeConfig{
- RegisterAddress{RegisterArea::M, 2},
- CoilMode::Normal});
- require(hold_result.succeeded && coil_result.succeeded,
- "parallel hold contact and output coil must be added");
-
- require(!service.findNode(logic_id, stop_result.id)->configured,
- "new logic nodes must remain unconfigured until properties are applied");
- require(service.updateNodeConfig(
- logic_id,
- stop_result.id,
- ContactNodeConfig{
- RegisterAddress{RegisterArea::M, 1},
- ContactMode::NormallyClosed})
- .succeeded,
- "applying logic node properties must succeed");
- require(service.findNode(logic_id, stop_result.id)->configured,
- "applying logic node properties must mark the node configured");
-
- const LadderRung *rung = service.findRung(logic_id, rung_id);
- require(rung != nullptr && rung->stages.size() == 2,
- "series conditions must occupy ordered stages");
- require(rung->stages.at(1).branches.size() == 2,
- "parallel conditions must share one stage");
- require(rung->output.has_value(), "rung output must be fixed separately");
- require(service.findLogic(logic_id)->validate(),
- "configured self-hold ladder must pass full validation");
-
- const LogicNode *start = service.findNode(logic_id, start_result.id);
- require(start != nullptr, "added condition must be discoverable");
- require(service.updateNodeConfig(
- logic_id,
- start_result.id,
- ContactNodeConfig{
- RegisterAddress{RegisterArea::M, 2},
- ContactMode::NormallyClosed})
- .succeeded,
- "contact properties must be editable");
-
- require(service.removeNode(logic_id, hold_result.id).succeeded,
- "parallel branch deletion must succeed");
- require(service.findRung(logic_id, rung_id)->stages.at(1).branches.size() == 1,
- "deleting one branch must keep the ladder stage");
- require(service.removeNode(logic_id, start_result.id).succeeded,
- "last branch deletion must succeed");
- require(service.findRung(logic_id, rung_id)->stages.size() == 1,
- "deleting the last branch must remove the empty stage");
-
- const LogicEditorResult second_rung = service.addRung(logic_id);
- require(second_rung.succeeded, "additional ladder rungs must be supported");
- require(service.removeRung(logic_id, second_rung.id).succeeded,
- "additional ladder rungs must be removable");
- require(!service.removeRung(logic_id, rung_id).succeeded,
- "the only remaining ladder rung must not be removed");
- }
-
- } // namespace
-
- int main()
- {
- try
- {
- testEditorOperations();
- }
- catch (const std::exception &error)
- {
- std::cerr << "logic editor service tests failed: " << error.what() << '\n';
- return 1;
- }
-
- std::cout << "logic editor service tests passed\n";
- return 0;
- }
|