blob: ef35fc57e91a17602e334b6e3cf7f032f7b8a35c [file] [log] [blame] [edit]
#include "device/device_factory.hpp"
#include "modbus_server_tester.hpp"
#include "port/base_port.hpp"
#include "test_base.hpp"
#include <xyz/openbmc_project/Software/Version/client.hpp>
#include <gtest/gtest.h>
using namespace std::literals;
using namespace testing;
using SoftwareIntf =
sdbusplus::client::xyz::openbmc_project::software::Version<>;
namespace ModbusIntf = phosphor::modbus::rtu;
namespace PortIntf = phosphor::modbus::rtu::port;
namespace PortConfigIntf = PortIntf::config;
namespace DeviceIntf = phosphor::modbus::rtu::device;
namespace DeviceConfigIntf = DeviceIntf::config;
class MockPort : public PortIntf::BasePort
{
public:
MockPort(sdbusplus::async::context& ctx,
const PortConfigIntf::Config& config,
const std::string& devicePath) : BasePort(ctx, config, devicePath)
{}
};
class TestFirmware : public DeviceIntf::DeviceFirmware
{
public:
TestFirmware(sdbusplus::async::context& ctx,
const DeviceConfigIntf::Config& config,
PortIntf::BasePort& serialPort) :
DeviceIntf::DeviceFirmware(ctx, config, serialPort)
{}
auto getObjectPath() -> sdbusplus::message::object_path
{
return objectPath;
}
};
class FirmwareTest : public BaseTest
{
public:
static constexpr auto clientDevicePath = "/tmp/ttyFirmwareTestPort0";
static constexpr auto serverDevicePath = "/tmp/ttyFirmwareTestPort1";
static constexpr auto portName = "TestPort0";
static constexpr auto serviceName =
"xyz.openbmc_project.TestModbusRTUFirmware";
static constexpr auto firmwareName = "TestVersion";
PortConfigIntf::Config portConfig;
std::string deviceName;
std::string objectPath;
std::unique_ptr<MockPort> mockPort;
FirmwareTest() : BaseTest(clientDevicePath, serverDevicePath, serviceName)
{
portConfig.name = portName;
portConfig.portMode = PortConfigIntf::PortMode::rs485;
portConfig.baudRate = baudRate;
portConfig.rtsDelay = 1;
deviceName = std::format("ResorviorPumpUnit_{}_{}",
TestIntf::testDeviceAddress, portName);
objectPath =
std::format("{}/{}", SoftwareIntf::namespace_path, deviceName);
mockPort =
std::make_unique<MockPort>(ctx, portConfig, clientDevicePath);
}
auto testFirmwareVersion(
std::string objectPath,
DeviceConfigIntf::FirmwareRegister firmwareRegister,
std::string expectedVersion) -> sdbusplus::async::task<void>
{
DeviceConfigIntf::DeviceFactoryConfig deviceFactoryConfig = {
{
.address = TestIntf::testDeviceAddress,
.parity = ModbusIntf::Parity::none,
.baudRate = baudRate,
.name = deviceName,
.portName = portConfig.name,
.inventoryPath = sdbusplus::message::object_path(
"xyz/openbmc_project/Inventory/ResorviorPumpUnit"),
.sensorRegisters = {},
.statusRegisters = {},
.firmwareRegisters = {firmwareRegister},
},
DeviceConfigIntf::DeviceType::reservoirPumpUnit,
DeviceConfigIntf::DeviceModel::RDF040DSS5193E0,
};
auto deviceFirmware =
std::make_unique<TestFirmware>(ctx, deviceFactoryConfig, *mockPort);
co_await deviceFirmware->readVersionRegister();
EXPECT_TRUE(deviceFirmware->getObjectPath().str.starts_with(objectPath))
<< "Invalid ObjectPath";
auto softwarePath = deviceFirmware->getObjectPath().str;
auto properties = co_await SoftwareIntf(ctx)
.service(serviceName)
.path(softwarePath)
.properties();
EXPECT_EQ(properties.version, expectedVersion)
<< "Firmware version mismatch";
co_return;
}
};
TEST_F(FirmwareTest, TestFirmwareVersion)
{
const DeviceConfigIntf::FirmwareRegister firmwareRegister = {
.name = "",
.type = DeviceConfigIntf::FirmwareRegisterType::version,
.offset = TestIntf::testReadHoldingRegisterFirmwareVersionOffset,
.size = TestIntf::testReadHoldingRegisterFirmwareVersionCount};
ctx.spawn(testFirmwareVersion(
objectPath, firmwareRegister,
TestIntf::testReadHoldingRegisterFirmwareVersionStr));
ctx.spawn(sdbusplus::async::sleep_for(ctx, 1s) |
sdbusplus::async::execution::then([&]() { ctx.request_stop(); }));
ctx.run();
}