|
- #include "domain/control_logic_model.h"
- #include "domain/register_repository.h"
- #include "domain/virtual_register_repository.h"
- #include "services/software_logic_executor.h"
-
- #include <QDebug>
- #include <QTest>
-
- #include <cstdint>
- #include <string>
- #include <utility>
- #include <vector>
-
- namespace
- {
-
- LogicNode contact(const std::string &id, int address)
- {
- return {id,
- ContactNodeConfig{
- RegisterAddress{RegisterArea::M, address},
- ContactMode::NormallyOpen},
- true};
- }
-
- LogicNode coil(const std::string &id, int address)
- {
- return {id,
- CoilNodeConfig{
- RegisterAddress{RegisterArea::M, address},
- CoilMode::Normal},
- true};
- }
-
- ControlLogic makeLogic(int index, int rung_count = 1)
- {
- ControlLogic logic;
- logic.id = "logic-" + std::to_string(index);
- logic.name = logic.id;
- logic.enabled = true;
-
- for (int rung_index = 0; rung_index < rung_count; ++rung_index)
- {
- const int object_index = index * rung_count + rung_index;
- LadderRung rung;
- rung.id = "rung-" + std::to_string(index) + "-"
- + std::to_string(rung_index);
- rung.name = rung.id;
- for (int column = 0;
- column < ProjectLimits::kMaximumConditionColumns;
- ++column)
- {
- rung.cells.push_back({
- rung.id + "-cell-" + std::to_string(column),
- column == 0 ? LadderCellKind::Node : LadderCellKind::Wire,
- column == 0
- ? std::optional<LogicNode>{contact(
- "contact-" + std::to_string(object_index),
- object_index)}
- : std::nullopt});
- }
- rung.output = coil(
- "coil-" + std::to_string(object_index), object_index + 1000);
- logic.rungs.push_back(std::move(rung));
- }
- return logic;
- }
-
- class PerformanceTests final : public QObject
- {
- Q_OBJECT
-
- private slots:
- void initTestCase()
- {
- qInfo().noquote()
- << QStringLiteral("性能测试开始:以下 RESULT 的耗时均为平均每次执行时间");
- qInfo().noquote()
- << QStringLiteral("测试项目 1:工程上限规模的软件扫描");
- qInfo().noquote()
- << QStringLiteral("测试项目 2:超出工程上限的扫描压力测试");
- qInfo().noquote()
- << QStringLiteral("测试项目 3:4001 个虚拟 M 地址的边界读写");
- qInfo().noquote()
- << QStringLiteral("测试项目 4:256 个连续 D 字的轮询规模读写");
- }
-
- void softwareExecutor_scansMaximumValidProject()
- {
- std::vector<ControlLogic> logics;
- logics.reserve(ProjectLimits::kMaximumControlLogics);
- for (std::size_t index = 0;
- index < ProjectLimits::kMaximumControlLogics;
- ++index)
- {
- logics.push_back(makeLogic(
- static_cast<int>(index), 64));
- }
-
- SoftwareLogicExecutor executor;
- VirtualRegisterRepository repository;
- QVERIFY(executor.validate(logics).succeeded);
- QVERIFY(executor.executeScan(logics, repository).succeeded);
-
- QBENCHMARK
- {
- executor.executeScan(logics, repository);
- }
- QVERIFY(executor.executeScan(logics, repository).succeeded);
- }
-
- void softwareExecutor_scansStressProject()
- {
- std::vector<ControlLogic> logics;
- logics.reserve(100);
- for (int index = 0; index < 100; ++index)
- {
- logics.push_back(makeLogic(index));
- }
-
- SoftwareLogicExecutor executor;
- VirtualRegisterRepository repository;
- QVERIFY(executor.validate(logics).succeeded);
-
- QBENCHMARK
- {
- executor.executeScan(logics, repository);
- }
- QVERIFY(executor.executeScan(logics, repository).succeeded);
- }
-
- void virtualRepository_handlesBoundaryBitWorkload()
- {
- VirtualRegisterRepository repository;
- for (int index = 0; index <= RegisterAddress::kMaximumIndex; ++index)
- {
- QVERIFY(repository.writeBit(
- {RegisterArea::M, index}, (index % 2) == 0)
- .succeeded);
- QVERIFY(repository.readBit({RegisterArea::M, index}).succeeded);
- }
-
- QBENCHMARK
- {
- for (int index = 0; index <= RegisterAddress::kMaximumIndex; ++index)
- {
- repository.writeBit(
- {RegisterArea::M, index}, (index % 2) == 0);
- repository.readBit({RegisterArea::M, index});
- }
- }
- QVERIFY(repository.readBit({RegisterArea::M, 0}).succeeded);
- QVERIFY(repository.readBit({RegisterArea::M, RegisterAddress::kMaximumIndex}).succeeded);
- }
-
- void virtualRepository_handlesPollSizedWordBlocks()
- {
- const int word_count = static_cast<int>(ProjectLimits::kMaximumPollAddresses);
- std::vector<std::int16_t> values(static_cast<std::size_t>(word_count));
- for (int index = 0; index < word_count; ++index)
- {
- values[static_cast<std::size_t>(index)] =
- static_cast<std::int16_t>(index);
- }
-
- VirtualRegisterRepository repository;
- QVERIFY(repository.writeWords(
- {RegisterArea::D, 0}, values)
- .succeeded);
- QVERIFY(repository.readWords(
- {RegisterArea::D, 0}, word_count)
- .succeeded);
-
- QBENCHMARK
- {
- repository.writeWords({RegisterArea::D, 0}, values);
- repository.readWords({RegisterArea::D, 0}, word_count);
- }
-
- const WordsReadResult result = repository.readWords(
- {RegisterArea::D, 0}, word_count);
- QVERIFY(result.succeeded && result.values == values);
- }
-
- void cleanupTestCase()
- {
- qInfo().noquote()
- << QStringLiteral("性能测试结束:请结合上方四项 RESULT 和最后的 Totals 判断结果");
- }
- };
-
- } // namespace
-
- QTEST_APPLESS_MAIN(PerformanceTests)
-
- #include "performance_tests.moc"
|