|
|
|
@@ -0,0 +1,143 @@ |
|
|
|
#include "domain/virtual_register_repository.h" |
|
|
|
#include "services/alarm_service.h" |
|
|
|
#include "services/hmi_editor_service.h" |
|
|
|
#include "services/hmi_navigation_service.h" |
|
|
|
#include "services/hmi_runtime_service.h" |
|
|
|
#include "services/logic_editor_service.h" |
|
|
|
#include "services/offline_simulation_service.h" |
|
|
|
#include "services/project_service.h" |
|
|
|
#include "services/register_monitor_service.h" |
|
|
|
#include "services/runtime_mode_service.h" |
|
|
|
#include "support/test_support.h" |
|
|
|
#include "ui/hmi_editor_widget.h" |
|
|
|
#include "ui/logic_editor_widget.h" |
|
|
|
#include "ui/runtime_panel_controller.h" |
|
|
|
|
|
|
|
#include <QApplication> |
|
|
|
#include <QCoreApplication> |
|
|
|
#include <QEventLoop> |
|
|
|
#include <QLabel> |
|
|
|
#include <QWidget> |
|
|
|
|
|
|
|
#include <iostream> |
|
|
|
#include <stdexcept> |
|
|
|
#include <string> |
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
|
|
using TestProjectStorage = TestSupport::InMemoryProjectStorage; |
|
|
|
using TestSupport::require; |
|
|
|
|
|
|
|
ControlLogic makeAlwaysOnLogic() |
|
|
|
{ |
|
|
|
ControlLogic logic; |
|
|
|
logic.id = "queued-trace-logic"; |
|
|
|
logic.name = "Queued trace logic"; |
|
|
|
|
|
|
|
LadderRung rung; |
|
|
|
rung.id = "always-on-rung"; |
|
|
|
rung.name = "Always on"; |
|
|
|
rung.condition = ConditionExpression::fromWire("always-on-wire", 10); |
|
|
|
|
|
|
|
LogicNode output; |
|
|
|
output.id = "always-on-output"; |
|
|
|
output.config = CoilNodeConfig{ |
|
|
|
RegisterAddress{RegisterArea::M, 1}, CoilMode::Normal}; |
|
|
|
rung.output = output; |
|
|
|
logic.rungs.push_back(rung); |
|
|
|
return logic; |
|
|
|
} |
|
|
|
|
|
|
|
void testQueuedOfflineTraceIsIgnoredAfterReturningToEditing() |
|
|
|
{ |
|
|
|
TestProjectStorage storage; |
|
|
|
ProjectService project_service(storage); |
|
|
|
VirtualRegisterRepository virtual_repository; |
|
|
|
OfflineSimulationService simulation_service(virtual_repository); |
|
|
|
RuntimeModeService runtime_mode_service(project_service, simulation_service); |
|
|
|
HmiEditorService hmi_editor_service(project_service); |
|
|
|
HmiRuntimeService hmi_runtime_service(virtual_repository); |
|
|
|
LogicEditorService logic_editor_service(project_service); |
|
|
|
HmiNavigationService hmi_navigation_service(project_service); |
|
|
|
AlarmService alarm_service(project_service, virtual_repository); |
|
|
|
RegisterMonitorService register_monitor_service(virtual_repository); |
|
|
|
|
|
|
|
const ControlLogic logic = makeAlwaysOnLogic(); |
|
|
|
project_service.editProject().controlLogics.push_back(logic); |
|
|
|
|
|
|
|
QWidget parent; |
|
|
|
HmiEditorWidget hmi_editor_widget( |
|
|
|
hmi_editor_service, hmi_runtime_service, alarm_service, &parent); |
|
|
|
LogicEditorWidget logic_editor_widget(logic_editor_service, &parent); |
|
|
|
QLabel executor_status_label(&parent); |
|
|
|
std::string current_logic_id = logic.id; |
|
|
|
logic_editor_widget.setLogicId(current_logic_id); |
|
|
|
|
|
|
|
RuntimePanelController controller( |
|
|
|
parent, |
|
|
|
runtime_mode_service, |
|
|
|
project_service, |
|
|
|
hmi_editor_service, |
|
|
|
hmi_runtime_service, |
|
|
|
logic_editor_service, |
|
|
|
hmi_navigation_service, |
|
|
|
alarm_service, |
|
|
|
register_monitor_service, |
|
|
|
hmi_editor_widget, |
|
|
|
logic_editor_widget, |
|
|
|
executor_status_label, |
|
|
|
[¤t_logic_id] { return current_logic_id; }, |
|
|
|
[¤t_logic_id](const std::string &logic_id) |
|
|
|
{ |
|
|
|
current_logic_id = logic_id; |
|
|
|
}, |
|
|
|
[](const std::string &) {}, |
|
|
|
[](const QString &, int) {}, |
|
|
|
[](const QString &) {}, |
|
|
|
[] {}); |
|
|
|
controller.configure(); |
|
|
|
|
|
|
|
require(runtime_mode_service.enterOfflineRunning().succeeded, |
|
|
|
"offline simulation must start for queued trace regression"); |
|
|
|
controller.enterRuntime( |
|
|
|
{}, logic.id, runtime_mode_service.mode(), |
|
|
|
runtime_mode_service.plcConnectionState()); |
|
|
|
require(simulation_service.executeOnce().succeeded, |
|
|
|
"offline simulation must produce a trace before editing"); |
|
|
|
require(simulation_service.traceSnapshot() |
|
|
|
.forLogic(logic.id).rungValues.at("always-on-rung"), |
|
|
|
"the queued trace must contain an energized rung"); |
|
|
|
|
|
|
|
require(runtime_mode_service.enterEditing().succeeded, |
|
|
|
"offline simulation must return to editing before queued delivery"); |
|
|
|
controller.leaveRuntime( |
|
|
|
runtime_mode_service.mode(), runtime_mode_service.plcConnectionState()); |
|
|
|
logic_editor_widget.clearRuntimeTrace(); |
|
|
|
require(!logic_editor_widget.runtimeTraceEnabled(), |
|
|
|
"editing transition must initially clear the runtime trace"); |
|
|
|
|
|
|
|
QCoreApplication::processEvents(QEventLoop::AllEvents); |
|
|
|
require(!logic_editor_widget.runtimeTraceEnabled(), |
|
|
|
"a queued offline scan must not restore the trace after returning to editing"); |
|
|
|
} |
|
|
|
|
|
|
|
} // namespace |
|
|
|
|
|
|
|
int main(int argc, char *argv[]) |
|
|
|
{ |
|
|
|
qputenv("QT_QPA_PLATFORM", QByteArrayLiteral("offscreen")); |
|
|
|
QApplication application(argc, argv); |
|
|
|
try |
|
|
|
{ |
|
|
|
testQueuedOfflineTraceIsIgnoredAfterReturningToEditing(); |
|
|
|
} |
|
|
|
catch (const std::exception &error) |
|
|
|
{ |
|
|
|
std::cerr << "runtime panel controller tests failed: " |
|
|
|
<< error.what() << '\n'; |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
std::cout << "runtime panel controller tests passed\n"; |
|
|
|
return 0; |
|
|
|
} |