blob: 547e0b2f71b689398607a7386d509c2d866a54e9 [file] [log] [blame]
#include "modbus/modbus_commands.hpp"
#include "modbus/modbus_exception.hpp"
#include <cstring>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
namespace RTUIntf = phosphor::modbus::rtu;
class ReadHoldingRegistersResponseTest :
public RTUIntf::ReadHoldingRegistersResponse
{
public:
ReadHoldingRegistersResponseTest(uint8_t address,
std::vector<uint16_t>& registers) :
RTUIntf::ReadHoldingRegistersResponse(address, registers)
{}
template <std::size_t Length>
ReadHoldingRegistersResponseTest& operator=(
const std::array<uint8_t, Length>& expectedMessage)
{
len = Length;
std::copy(expectedMessage.begin(), expectedMessage.end(), raw.begin());
return *this;
}
};
class ModbusCommandTest : public ::testing::Test
{
public:
ModbusCommandTest() = default;
static constexpr auto failureMessageLength = 11;
template <typename ExceptionType, std::size_t Length>
void TestReadHoldingRegisterResponseFailure(
const std::array<uint8_t, Length>& expectedMessage)
{
constexpr uint8_t expectedAddress = 0xa;
constexpr size_t expectedRegisterSize = 3;
std::vector<uint16_t> registers(expectedRegisterSize);
ReadHoldingRegistersResponseTest response(expectedAddress, registers);
response = expectedMessage;
EXPECT_THROW(response.decode(), ExceptionType);
}
};
TEST_F(ModbusCommandTest, TestReadHoldingRegistersRequestSucess)
{
constexpr size_t expectedLength = 8;
constexpr uint8_t expectedAddress = 0x1;
constexpr std::array<uint8_t, expectedLength> expectedMessage = {
expectedAddress, // addr(1) = 0x01
0x03, // func(1) = 0x03
0x12, // reg_off(2) = 0x1234
0x34,
0x00, // reg_cnt(2) = 0x0020,
0x20,
0x00, // crc(2) (Pre-computed) = 0xa4
0xa4};
RTUIntf::ReadHoldingRegistersRequest request(expectedAddress, 0x1234, 0x20);
request.encode();
std::array<uint8_t, expectedLength> actualMessage;
std::memcpy(actualMessage.data(), request.raw.data(), expectedLength);
EXPECT_EQ(actualMessage, expectedMessage);
EXPECT_EQ(request.address, expectedAddress);
}
TEST_F(ModbusCommandTest, TestReadHoldingRegistersResponseSucess)
{
constexpr size_t expectedLength = 11;
constexpr uint8_t expectedAddress = 0xa;
constexpr size_t expectedRegisterSize = 3;
constexpr std::array<uint8_t, expectedLength> expectedMessage = {
expectedAddress, // addr(1) = 0x0a
0x03, // func(1) = 0x03
0x06, // bytes(1) = 0x06
0x11, // regs(3*2) = 0x1122, 0x3344, 0x5566
0x22,
0x33,
0x44,
0x55,
0x66,
0x59, // crc(2) = 0x5928 (pre-computed)
0x28};
const std::vector<uint16_t> expectedRegisters{0x1122, 0x3344, 0x5566};
std::vector<uint16_t> registers(expectedRegisterSize);
RTUIntf::ReadHoldingRegistersResponse response(expectedAddress, registers);
EXPECT_EQ(response.len, expectedLength);
std::copy(expectedMessage.begin(), expectedMessage.end(),
response.raw.begin());
EXPECT_EQ(response.len, expectedLength);
response.decode();
EXPECT_EQ(registers, expectedRegisters);
}
TEST_F(ModbusCommandTest, TestReadHoldingRegistersResponseError)
{
constexpr std::array<uint8_t, 5> expectedMessage = {
0xa, // addr(1) = 0x0a
0x83, // func(1) = 0x83
0x03, // exception code(1) = 0x03
0x70, // crc(2) = 0x70f3 (pre-computed)
0xf3};
TestReadHoldingRegisterResponseFailure<RTUIntf::ModbusException>(
expectedMessage);
}
TEST_F(ModbusCommandTest, TestReadHoldingRegistersResponseBadAddress)
{
constexpr std::array<uint8_t, failureMessageLength> expectedMessage = {
0x1, // Bad address(1), should be 0x0a
0x03, // func(1) = 0x03
0x06, // bytes(1) = 0x06
0x11, // regs(3*2) = 0x1122, 0x3344, 0x5566
0x22, 0x33, 0x44, 0x55, 0x66,
0x2a, // crc(2) = 0x2a18 (pre-computed)
0x18};
TestReadHoldingRegisterResponseFailure<RTUIntf::ModbusBadResponseException>(
expectedMessage);
}
TEST_F(ModbusCommandTest, TestReadHoldingRegistersResponseBadCRC)
{
constexpr std::array<uint8_t, failureMessageLength> expectedMessage = {
0xa, // addr(1) = 0x0a
0x03, // func(1) = 0x03
0x06, // bytes(1) = 0x06
0x11, // regs(3*2) = 0x1122, 0x3344, 0x5566
0x22, 0x33, 0x44, 0x55, 0x66,
0x59, // Bad crc(2), should be 0x5928
0x29};
TestReadHoldingRegisterResponseFailure<RTUIntf::ModbusCRCException>(
expectedMessage);
}
TEST_F(ModbusCommandTest, TestReadHoldingRegistersResponseBadFunctionCode)
{
constexpr std::array<uint8_t, failureMessageLength> expectedMessage = {
0xa, // addr(1) = 0x0a
0x04, // Bad function code(1), should be 0x03
0x06, // bytes(1) = 0x06
0x11, // regs(3*2) = 0x1122, 0x3344, 0x5566
0x22, 0x33, 0x44, 0x55, 0x66,
0x18, // crc(2) = 0x18ce (pre-computed)
0xce};
TestReadHoldingRegisterResponseFailure<RTUIntf::ModbusBadResponseException>(
expectedMessage);
}
TEST_F(ModbusCommandTest, TestReadHoldingRegistersResponseBadByteCount)
{
constexpr std::array<uint8_t, failureMessageLength> expectedMessage = {
0xa, // addr(1) = 0x0a
0x03, // func(1) = 0x03
0x04, // Bad bytes(1), should be 0x06
0x11, // regs(3*2) = 0x1122, 0x3344, 0x5566
0x22, 0x33, 0x44, 0x55, 0x66,
0x7a, // crc(2) = 0x7ae8 (pre-computed)
0xe8};
TestReadHoldingRegisterResponseFailure<RTUIntf::ModbusBadResponseException>(
expectedMessage);
}