xref: /openbmc/phosphor-modbus/tests/test_modbus_commands.cpp (revision 9695bd284570b51677c11529103929c8e51da6b6)
1*9695bd28SJagpal Singh Gill #include "modbus/modbus_commands.hpp"
2*9695bd28SJagpal Singh Gill #include "modbus/modbus_exception.hpp"
3*9695bd28SJagpal Singh Gill 
4*9695bd28SJagpal Singh Gill #include <cstring>
5*9695bd28SJagpal Singh Gill 
6*9695bd28SJagpal Singh Gill #include <gmock/gmock.h>
7*9695bd28SJagpal Singh Gill #include <gtest/gtest.h>
8*9695bd28SJagpal Singh Gill 
9*9695bd28SJagpal Singh Gill namespace RTUIntf = phosphor::modbus::rtu;
10*9695bd28SJagpal Singh Gill 
11*9695bd28SJagpal Singh Gill class ReadHoldingRegistersResponseTest :
12*9695bd28SJagpal Singh Gill     public RTUIntf::ReadHoldingRegistersResponse
13*9695bd28SJagpal Singh Gill {
14*9695bd28SJagpal Singh Gill   public:
ReadHoldingRegistersResponseTest(uint8_t address,std::vector<uint16_t> & registers)15*9695bd28SJagpal Singh Gill     ReadHoldingRegistersResponseTest(uint8_t address,
16*9695bd28SJagpal Singh Gill                                      std::vector<uint16_t>& registers) :
17*9695bd28SJagpal Singh Gill         RTUIntf::ReadHoldingRegistersResponse(address, registers)
18*9695bd28SJagpal Singh Gill     {}
19*9695bd28SJagpal Singh Gill 
20*9695bd28SJagpal Singh Gill     template <std::size_t Length>
operator =(const std::array<uint8_t,Length> & expectedMessage)21*9695bd28SJagpal Singh Gill     ReadHoldingRegistersResponseTest& operator=(
22*9695bd28SJagpal Singh Gill         const std::array<uint8_t, Length>& expectedMessage)
23*9695bd28SJagpal Singh Gill     {
24*9695bd28SJagpal Singh Gill         len = Length;
25*9695bd28SJagpal Singh Gill         std::copy(expectedMessage.begin(), expectedMessage.end(), raw.begin());
26*9695bd28SJagpal Singh Gill         return *this;
27*9695bd28SJagpal Singh Gill     }
28*9695bd28SJagpal Singh Gill };
29*9695bd28SJagpal Singh Gill 
30*9695bd28SJagpal Singh Gill class ModbusCommandTest : public ::testing::Test
31*9695bd28SJagpal Singh Gill {
32*9695bd28SJagpal Singh Gill   public:
33*9695bd28SJagpal Singh Gill     ModbusCommandTest() = default;
34*9695bd28SJagpal Singh Gill 
35*9695bd28SJagpal Singh Gill     static constexpr auto failureMessageLength = 11;
36*9695bd28SJagpal Singh Gill 
37*9695bd28SJagpal Singh Gill     template <typename ExceptionType, std::size_t Length>
TestReadHoldingRegisterResponseFailure(const std::array<uint8_t,Length> & expectedMessage)38*9695bd28SJagpal Singh Gill     void TestReadHoldingRegisterResponseFailure(
39*9695bd28SJagpal Singh Gill         const std::array<uint8_t, Length>& expectedMessage)
40*9695bd28SJagpal Singh Gill     {
41*9695bd28SJagpal Singh Gill         constexpr uint8_t expectedAddress = 0xa;
42*9695bd28SJagpal Singh Gill         constexpr size_t expectedRegisterSize = 3;
43*9695bd28SJagpal Singh Gill         std::vector<uint16_t> registers(expectedRegisterSize);
44*9695bd28SJagpal Singh Gill         ReadHoldingRegistersResponseTest response(expectedAddress, registers);
45*9695bd28SJagpal Singh Gill         response = expectedMessage;
46*9695bd28SJagpal Singh Gill 
47*9695bd28SJagpal Singh Gill         EXPECT_THROW(response.decode(), ExceptionType);
48*9695bd28SJagpal Singh Gill     }
49*9695bd28SJagpal Singh Gill };
50*9695bd28SJagpal Singh Gill 
TEST_F(ModbusCommandTest,TestReadHoldingRegistersRequestSucess)51*9695bd28SJagpal Singh Gill TEST_F(ModbusCommandTest, TestReadHoldingRegistersRequestSucess)
52*9695bd28SJagpal Singh Gill {
53*9695bd28SJagpal Singh Gill     constexpr size_t expectedLength = 8;
54*9695bd28SJagpal Singh Gill     constexpr uint8_t expectedAddress = 0x1;
55*9695bd28SJagpal Singh Gill     constexpr std::array<uint8_t, expectedLength> expectedMessage = {
56*9695bd28SJagpal Singh Gill         expectedAddress, // addr(1) = 0x01
57*9695bd28SJagpal Singh Gill         0x03,            // func(1) = 0x03
58*9695bd28SJagpal Singh Gill         0x12,            // reg_off(2) = 0x1234
59*9695bd28SJagpal Singh Gill         0x34,
60*9695bd28SJagpal Singh Gill         0x00,            // reg_cnt(2) = 0x0020,
61*9695bd28SJagpal Singh Gill         0x20,
62*9695bd28SJagpal Singh Gill         0x00,            // crc(2) (Pre-computed) = 0xa4
63*9695bd28SJagpal Singh Gill         0xa4};
64*9695bd28SJagpal Singh Gill 
65*9695bd28SJagpal Singh Gill     RTUIntf::ReadHoldingRegistersRequest request(expectedAddress, 0x1234, 0x20);
66*9695bd28SJagpal Singh Gill     request.encode();
67*9695bd28SJagpal Singh Gill 
68*9695bd28SJagpal Singh Gill     std::array<uint8_t, expectedLength> actualMessage;
69*9695bd28SJagpal Singh Gill     std::memcpy(actualMessage.data(), request.raw.data(), expectedLength);
70*9695bd28SJagpal Singh Gill 
71*9695bd28SJagpal Singh Gill     EXPECT_EQ(actualMessage, expectedMessage);
72*9695bd28SJagpal Singh Gill     EXPECT_EQ(request.address, expectedAddress);
73*9695bd28SJagpal Singh Gill }
74*9695bd28SJagpal Singh Gill 
TEST_F(ModbusCommandTest,TestReadHoldingRegistersResponseSucess)75*9695bd28SJagpal Singh Gill TEST_F(ModbusCommandTest, TestReadHoldingRegistersResponseSucess)
76*9695bd28SJagpal Singh Gill {
77*9695bd28SJagpal Singh Gill     constexpr size_t expectedLength = 11;
78*9695bd28SJagpal Singh Gill     constexpr uint8_t expectedAddress = 0xa;
79*9695bd28SJagpal Singh Gill     constexpr size_t expectedRegisterSize = 3;
80*9695bd28SJagpal Singh Gill     constexpr std::array<uint8_t, expectedLength> expectedMessage = {
81*9695bd28SJagpal Singh Gill         expectedAddress, // addr(1) = 0x0a
82*9695bd28SJagpal Singh Gill         0x03,            // func(1) = 0x03
83*9695bd28SJagpal Singh Gill         0x06,            // bytes(1) = 0x06
84*9695bd28SJagpal Singh Gill         0x11,            // regs(3*2) = 0x1122, 0x3344, 0x5566
85*9695bd28SJagpal Singh Gill         0x22,
86*9695bd28SJagpal Singh Gill         0x33,
87*9695bd28SJagpal Singh Gill         0x44,
88*9695bd28SJagpal Singh Gill         0x55,
89*9695bd28SJagpal Singh Gill         0x66,
90*9695bd28SJagpal Singh Gill         0x59, // crc(2) = 0x5928 (pre-computed)
91*9695bd28SJagpal Singh Gill         0x28};
92*9695bd28SJagpal Singh Gill     const std::vector<uint16_t> expectedRegisters{0x1122, 0x3344, 0x5566};
93*9695bd28SJagpal Singh Gill     std::vector<uint16_t> registers(expectedRegisterSize);
94*9695bd28SJagpal Singh Gill 
95*9695bd28SJagpal Singh Gill     RTUIntf::ReadHoldingRegistersResponse response(expectedAddress, registers);
96*9695bd28SJagpal Singh Gill     EXPECT_EQ(response.len, expectedLength);
97*9695bd28SJagpal Singh Gill 
98*9695bd28SJagpal Singh Gill     std::copy(expectedMessage.begin(), expectedMessage.end(),
99*9695bd28SJagpal Singh Gill               response.raw.begin());
100*9695bd28SJagpal Singh Gill 
101*9695bd28SJagpal Singh Gill     EXPECT_EQ(response.len, expectedLength);
102*9695bd28SJagpal Singh Gill     response.decode();
103*9695bd28SJagpal Singh Gill     EXPECT_EQ(registers, expectedRegisters);
104*9695bd28SJagpal Singh Gill }
105*9695bd28SJagpal Singh Gill 
TEST_F(ModbusCommandTest,TestReadHoldingRegistersResponseError)106*9695bd28SJagpal Singh Gill TEST_F(ModbusCommandTest, TestReadHoldingRegistersResponseError)
107*9695bd28SJagpal Singh Gill {
108*9695bd28SJagpal Singh Gill     constexpr std::array<uint8_t, 5> expectedMessage = {
109*9695bd28SJagpal Singh Gill         0xa,  // addr(1) = 0x0a
110*9695bd28SJagpal Singh Gill         0x83, // func(1) = 0x83
111*9695bd28SJagpal Singh Gill         0x03, // exception code(1) = 0x03
112*9695bd28SJagpal Singh Gill         0x70, // crc(2) = 0x70f3 (pre-computed)
113*9695bd28SJagpal Singh Gill         0xf3};
114*9695bd28SJagpal Singh Gill 
115*9695bd28SJagpal Singh Gill     TestReadHoldingRegisterResponseFailure<RTUIntf::ModbusException>(
116*9695bd28SJagpal Singh Gill         expectedMessage);
117*9695bd28SJagpal Singh Gill }
118*9695bd28SJagpal Singh Gill 
TEST_F(ModbusCommandTest,TestReadHoldingRegistersResponseBadAddress)119*9695bd28SJagpal Singh Gill TEST_F(ModbusCommandTest, TestReadHoldingRegistersResponseBadAddress)
120*9695bd28SJagpal Singh Gill {
121*9695bd28SJagpal Singh Gill     constexpr std::array<uint8_t, failureMessageLength> expectedMessage = {
122*9695bd28SJagpal Singh Gill         0x1,  // Bad address(1), should be 0x0a
123*9695bd28SJagpal Singh Gill         0x03, // func(1) = 0x03
124*9695bd28SJagpal Singh Gill         0x06, // bytes(1) = 0x06
125*9695bd28SJagpal Singh Gill         0x11, // regs(3*2) = 0x1122, 0x3344, 0x5566
126*9695bd28SJagpal Singh Gill         0x22, 0x33, 0x44, 0x55, 0x66,
127*9695bd28SJagpal Singh Gill         0x2a, // crc(2) = 0x2a18 (pre-computed)
128*9695bd28SJagpal Singh Gill         0x18};
129*9695bd28SJagpal Singh Gill 
130*9695bd28SJagpal Singh Gill     TestReadHoldingRegisterResponseFailure<RTUIntf::ModbusBadResponseException>(
131*9695bd28SJagpal Singh Gill         expectedMessage);
132*9695bd28SJagpal Singh Gill }
133*9695bd28SJagpal Singh Gill 
TEST_F(ModbusCommandTest,TestReadHoldingRegistersResponseBadCRC)134*9695bd28SJagpal Singh Gill TEST_F(ModbusCommandTest, TestReadHoldingRegistersResponseBadCRC)
135*9695bd28SJagpal Singh Gill {
136*9695bd28SJagpal Singh Gill     constexpr std::array<uint8_t, failureMessageLength> expectedMessage = {
137*9695bd28SJagpal Singh Gill         0xa,  // addr(1) = 0x0a
138*9695bd28SJagpal Singh Gill         0x03, // func(1) = 0x03
139*9695bd28SJagpal Singh Gill         0x06, // bytes(1) = 0x06
140*9695bd28SJagpal Singh Gill         0x11, // regs(3*2) = 0x1122, 0x3344, 0x5566
141*9695bd28SJagpal Singh Gill         0x22, 0x33, 0x44, 0x55, 0x66,
142*9695bd28SJagpal Singh Gill         0x59, // Bad crc(2), should be 0x5928
143*9695bd28SJagpal Singh Gill         0x29};
144*9695bd28SJagpal Singh Gill 
145*9695bd28SJagpal Singh Gill     TestReadHoldingRegisterResponseFailure<RTUIntf::ModbusCRCException>(
146*9695bd28SJagpal Singh Gill         expectedMessage);
147*9695bd28SJagpal Singh Gill }
148*9695bd28SJagpal Singh Gill 
TEST_F(ModbusCommandTest,TestReadHoldingRegistersResponseBadFunctionCode)149*9695bd28SJagpal Singh Gill TEST_F(ModbusCommandTest, TestReadHoldingRegistersResponseBadFunctionCode)
150*9695bd28SJagpal Singh Gill {
151*9695bd28SJagpal Singh Gill     constexpr std::array<uint8_t, failureMessageLength> expectedMessage = {
152*9695bd28SJagpal Singh Gill         0xa,  // addr(1) = 0x0a
153*9695bd28SJagpal Singh Gill         0x04, // Bad function code(1), should be 0x03
154*9695bd28SJagpal Singh Gill         0x06, // bytes(1) = 0x06
155*9695bd28SJagpal Singh Gill         0x11, // regs(3*2) = 0x1122, 0x3344, 0x5566
156*9695bd28SJagpal Singh Gill         0x22, 0x33, 0x44, 0x55, 0x66,
157*9695bd28SJagpal Singh Gill         0x18, // crc(2) = 0x18ce (pre-computed)
158*9695bd28SJagpal Singh Gill         0xce};
159*9695bd28SJagpal Singh Gill 
160*9695bd28SJagpal Singh Gill     TestReadHoldingRegisterResponseFailure<RTUIntf::ModbusBadResponseException>(
161*9695bd28SJagpal Singh Gill         expectedMessage);
162*9695bd28SJagpal Singh Gill }
163*9695bd28SJagpal Singh Gill 
TEST_F(ModbusCommandTest,TestReadHoldingRegistersResponseBadByteCount)164*9695bd28SJagpal Singh Gill TEST_F(ModbusCommandTest, TestReadHoldingRegistersResponseBadByteCount)
165*9695bd28SJagpal Singh Gill {
166*9695bd28SJagpal Singh Gill     constexpr std::array<uint8_t, failureMessageLength> expectedMessage = {
167*9695bd28SJagpal Singh Gill         0xa,  // addr(1) = 0x0a
168*9695bd28SJagpal Singh Gill         0x03, // func(1) = 0x03
169*9695bd28SJagpal Singh Gill         0x04, // Bad bytes(1), should be 0x06
170*9695bd28SJagpal Singh Gill         0x11, // regs(3*2) = 0x1122, 0x3344, 0x5566
171*9695bd28SJagpal Singh Gill         0x22, 0x33, 0x44, 0x55, 0x66,
172*9695bd28SJagpal Singh Gill         0x7a, // crc(2) = 0x7ae8 (pre-computed)
173*9695bd28SJagpal Singh Gill         0xe8};
174*9695bd28SJagpal Singh Gill 
175*9695bd28SJagpal Singh Gill     TestReadHoldingRegisterResponseFailure<RTUIntf::ModbusBadResponseException>(
176*9695bd28SJagpal Singh Gill         expectedMessage);
177*9695bd28SJagpal Singh Gill }
178