#include "domain/project_storage.h" #include "services/logic_editor_service.h" #include "services/project_service.h" #include #include #include 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 LogicEditorResult start_result = service.addNode( logic_id, ContactNodeConfig{ RegisterAddress{RegisterArea::M, 0}, ContactMode::NormallyOpen}, {80, 80}); const LogicEditorResult coil_result = service.addNode( logic_id, CoilNodeConfig{ RegisterAddress{RegisterArea::M, 1}, CoilMode::Normal}, {360, 80}); require(start_result.succeeded && coil_result.succeeded, "contact and coil must be added"); require(service.connectNodes(logic_id, start_result.id, coil_result.id).succeeded, "valid nodes must connect"); require(!service.connectNodes(logic_id, start_result.id, coil_result.id).succeeded, "duplicate node connections must fail"); require(!service.connectNodes(logic_id, coil_result.id, start_result.id).succeeded, "coil outgoing connection must fail"); const LogicNode *start = service.findNode(logic_id, start_result.id); require(start != nullptr && start->position.x == 80, "added node position must be stored"); require(service.moveNode(logic_id, start_result.id, {120, 160}).succeeded, "node position must be editable"); 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, start_result.id).succeeded, "node deletion must succeed"); require(service.findNode(logic_id, start_result.id) == nullptr, "deleted node must disappear"); require(service.findLogic(logic_id)->connections.empty(), "deleting a node must remove its connections"); } } // 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; }