|
- #include "domain/active_register_repository.h"
- #include "domain/register_monitor_model.h"
- #include "domain/register_repository.h"
- #include "services/register_monitor_service.h"
-
- #include <iostream>
- #include <stdexcept>
- #include <string>
-
- namespace {
-
- void require(bool condition, const std::string &message)
- {
- if (!condition)
- {
- throw std::runtime_error(message);
- }
- }
-
- void testRangeManagement()
- {
- VirtualRegisterRepository repository;
- RegisterMonitorService service(repository);
- int change_count = 0;
- service.setAddressesChangedCallback([&change_count] { ++change_count; });
-
- const RegisterMonitorResult added = service.addRange(" d10 ", 3);
- require(added.succeeded && added.affectedCount == 3
- && service.addresses().size() == 3U,
- "monitor service must expand a normalized continuous address range");
- require(service.addresses().front() == RegisterAddress{RegisterArea::D, 10}
- && service.addresses().back() == RegisterAddress{RegisterArea::D, 12},
- "monitor service must preserve expanded address order");
- const RegisterMonitorResult duplicate = service.addRange("D11", 2);
- require(!duplicate.succeeded && duplicate.error == RegisterMonitorError::NoChange,
- "monitor service must reject a fully duplicated range");
- require(!service.addRange("M4000", 2).succeeded,
- "monitor service must reject a range crossing address 4000");
- require(change_count == 1,
- "failed additions must not report a monitor address change");
-
- require(service.remove({RegisterAddress{RegisterArea::D, 11}}).succeeded
- && service.addresses().size() == 2U,
- "monitor service must remove selected addresses");
- require(service.clear().succeeded && service.addresses().empty(),
- "monitor service must clear the current monitor table");
- require(change_count == 3,
- "successful add, remove and clear operations must notify address changes");
- }
-
- void testSharedActiveRepositoryValues()
- {
- VirtualRegisterRepository virtual_repository;
- VirtualRegisterRepository plc_repository;
- ActiveRegisterRepository active_repository(virtual_repository);
- RegisterMonitorService service(active_repository);
- require(service.addRange("M0", 1).succeeded
- && service.addRange("D0", 1).succeeded,
- "monitor service must accept one M and one D address");
-
- virtual_repository.writeBit({RegisterArea::M, 0}, true);
- virtual_repository.writeWord({RegisterArea::D, 0}, -123);
- std::vector<MonitorValue> values = service.values(false);
- require(values.size() == 2U && values[0].bitValue && values[1].wordValue == -123,
- "monitor values must reflect the active virtual repository");
-
- plc_repository.writeBit({RegisterArea::M, 0}, false);
- plc_repository.writeWord({RegisterArea::D, 0}, 456);
- active_repository.use(plc_repository);
- values = service.values(false);
- require(!values[0].bitValue && values[1].wordValue == 456,
- "monitor values must follow the active repository switch");
- values = service.values(true);
- require(values[0].state == MonitorValueState::CommunicationFault
- && values[1].state == MonitorValueState::CommunicationFault,
- "valid cached values must be marked stale during a communication fault");
- }
-
- } // namespace
-
- int main()
- {
- try
- {
- testRangeManagement();
- testSharedActiveRepositoryValues();
- }
- catch (const std::exception &error)
- {
- std::cerr << "register monitor service tests failed: " << error.what() << '\n';
- return 1;
- }
- std::cout << "register monitor service tests passed\n";
- return 0;
- }
|