• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wirenboard / wb-mqtt-serial / 690

26 Aug 2025 01:28PM UTC coverage: 73.031%. Remained the same
690

push

github

web-flow
Add protocol parameter to device/Probe RPC (#988)

  * Add protocol to Modbus TCP port information in ports/Load RPC
  * Add protocol parameter to device/Probe RPC
  * Set TCP_NODELAY for TCP ports
  * Handle TCP port closing by remote

6605 of 9406 branches covered (70.22%)

28 of 59 new or added lines in 11 files covered. (47.46%)

136 existing lines in 8 files now uncovered.

12554 of 17190 relevant lines covered (73.03%)

372.2 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.61
/test/modbus_tcp_test.cpp
1
#include "fake_serial_port.h"
2
#include "modbus_common.h"
3

4
namespace
5
{
6
    class TPortMock: public TPort
7
    {
8
        size_t Pointer = 0;
9
        std::vector<uint8_t> Stream;
10
        std::vector<uint8_t> LastRequest;
11

12
    public:
13
        TPortMock(const std::vector<uint8_t>& stream): Stream(stream)
8✔
14
        {}
8✔
15

16
        void Open() override
×
17
        {}
18
        void Close() override
×
19
        {}
20
        bool IsOpen() const override
×
21
        {
22
            return false;
×
23
        }
24
        void CheckPortOpen() const override
×
25
        {}
26

27
        void WriteBytes(const uint8_t* buf, int count) override
9✔
28
        {
29
            LastRequest.assign(buf, buf + count);
9✔
30
        }
9✔
31

32
        uint8_t ReadByte(const std::chrono::microseconds& timeout) override
×
33
        {
34
            return 0;
×
35
        }
36

37
        TReadFrameResult ReadFrame(uint8_t* buf,
22✔
38
                                   size_t count,
39
                                   const std::chrono::microseconds& responseTimeout,
40
                                   const std::chrono::microseconds& frameTimeout,
41
                                   TFrameCompletePred frame_complete = 0) override
42
        {
43
            TReadFrameResult res;
22✔
44
            if (Pointer == Stream.size()) {
22✔
45
                std::this_thread::sleep_for(std::chrono::milliseconds(15));
2✔
46
                Pointer = 0;
2✔
47
            }
48
            res.Count = std::min(count, Stream.size() - Pointer);
22✔
49
            memcpy(buf, &Stream[Pointer], res.Count);
22✔
50
            Pointer += res.Count;
22✔
51
            return res;
22✔
52
        }
53

54
        void SkipNoise() override
×
55
        {}
56

57
        void SleepSinceLastInteraction(const std::chrono::microseconds& us) override
×
58
        {}
59

60
        std::string GetDescription(bool verbose) const override
17✔
61
        {
62
            return std::string();
17✔
63
        }
64

65
        const std::vector<uint8_t>& GetLastRequest() const
4✔
66
        {
67
            return LastRequest;
4✔
68
        }
69

NEW
70
        std::chrono::microseconds GetSendTimeBytes(double bytesNumber) const override
×
71
        {
72
            // 8-N-2
NEW
73
            auto bits = std::ceil(11 * bytesNumber);
×
NEW
74
            return GetSendTimeBits(bits);
×
75
        }
76

NEW
77
        std::chrono::microseconds GetSendTimeBits(size_t bitsNumber) const override
×
78
        {
79
            // 115200 bps
NEW
80
            auto us = std::ceil((1000000.0 * bitsNumber) / 115200.0);
×
NEW
81
            return std::chrono::microseconds(static_cast<std::chrono::microseconds::rep>(us));
×
82
        }
83
    };
84
}
85

86
class TModbusTCPTraitsTest: public testing::Test
87
{
88
public:
89
    void TestEqual(const std::vector<uint8_t>& b1, const std::vector<uint8_t>& b2) const
4✔
90
    {
91
        ASSERT_EQ(b1.size(), b2.size());
4✔
92

93
        for (size_t i = 0; i < b1.size(); ++i) {
13✔
94
            ASSERT_EQ(b1[i], b2[i]) << i;
9✔
95
        }
96
    }
97
};
98

99
TEST_F(TModbusTCPTraitsTest, ReadFrameGood)
8✔
100
{
101
    std::vector<uint8_t> r = {0, 1, 0, 0, 0, 3, 100, 17, 18};
2✔
102
    TPortMock port(r);
2✔
103
    Modbus::TModbusTCPTraits::ResetTransactionId(port);
2✔
104
    Modbus::TModbusTCPTraits traits;
2✔
105
    std::chrono::milliseconds t(10);
2✔
106

107
    std::vector<uint8_t> req = {7, 8, 9};
2✔
108
    auto resp = traits.Transaction(port, 100, req, 2, t, t).Pdu;
2✔
109
    ASSERT_EQ(resp.size(), 2);
2✔
110
    TestEqual(resp, {17, 18});
2✔
111
}
112

113
TEST_F(TModbusTCPTraitsTest, ReadFrameSmallMBAP)
8✔
114
{
115
    TPortMock port({0, 1, 0, 0});
4✔
116
    Modbus::TModbusTCPTraits::ResetTransactionId(port);
2✔
117
    Modbus::TModbusTCPTraits traits;
2✔
118
    std::chrono::milliseconds t(10);
2✔
119

120
    std::vector<uint8_t> req = {7, 8, 9};
2✔
121
    ASSERT_THROW(traits.Transaction(port, 100, req, 2, t, t), Modbus::TMalformedResponseError);
2✔
122
}
123

124
TEST_F(TModbusTCPTraitsTest, ReadFrameSmallMBAPLength)
8✔
125
{
126
    TPortMock port({0, 1, 0, 0, 0, 0, 100, 7, 8, 9});
4✔
127
    Modbus::TModbusTCPTraits::ResetTransactionId(port);
2✔
128
    Modbus::TModbusTCPTraits traits;
2✔
129
    std::chrono::milliseconds t(10);
2✔
130

131
    std::vector<uint8_t> req = {7, 8, 9};
2✔
132
    ASSERT_THROW(traits.Transaction(port, 100, req, 2, t, t), Modbus::TMalformedResponseError);
2✔
133
}
134

135
TEST_F(TModbusTCPTraitsTest, ReadFrameSmallPDU)
8✔
136
{
137
    TPortMock port({0, 1, 0, 0, 0, 4, 100, 7});
4✔
138
    Modbus::TModbusTCPTraits::ResetTransactionId(port);
2✔
139
    Modbus::TModbusTCPTraits traits;
2✔
140
    std::chrono::milliseconds t(10);
2✔
141

142
    std::vector<uint8_t> req = {7, 8, 9};
2✔
143
    ASSERT_THROW(traits.Transaction(port, 100, req, 2, t, t), Modbus::TMalformedResponseError);
2✔
144
}
145

146
TEST_F(TModbusTCPTraitsTest, ReadFrameWrongUnitId)
8✔
147
{
148
    TPortMock port({0, 1, 0, 0, 0, 4, 101, 7, 8, 9});
4✔
149
    Modbus::TModbusTCPTraits::ResetTransactionId(port);
2✔
150
    Modbus::TModbusTCPTraits traits;
2✔
151
    std::chrono::milliseconds t(10);
2✔
152

153
    std::vector<uint8_t> req = {7, 8, 9};
2✔
154
    ASSERT_THROW(traits.Transaction(port, 100, req, 2, t, t), Modbus::TUnexpectedResponseError);
2✔
155
}
156

157
TEST_F(TModbusTCPTraitsTest, ReadFramePassWrongTransactionId)
8✔
158
{
159
    std::vector<uint8_t> goodResp = {0, 1, 0, 0, 0, 4, 100, 17, 18, 19};
4✔
160
    std::vector<uint8_t> r = {0, 2, 0, 0, 0, 8, 101, 7, 8, 9, 10, 11, 12, 13};
4✔
161
    r.insert(r.end(), goodResp.begin(), goodResp.end());
2✔
162
    TPortMock port(r);
4✔
163

164
    Modbus::TModbusTCPTraits::ResetTransactionId(port);
2✔
165
    Modbus::TModbusTCPTraits traits;
4✔
166
    std::chrono::milliseconds t(10);
2✔
167

168
    std::vector<uint8_t> req = {7, 8, 9};
2✔
169
    TestEqual(traits.Transaction(port, 100, req, 2, t, t).Pdu, {17, 18, 19});
2✔
170
}
2✔
171

172
TEST_F(TModbusTCPTraitsTest, ReadFrameTimeout)
8✔
173
{
174
    TPortMock port({0, 2, 0, 0, 0, 4, 101, 7, 8, 9});
4✔
175
    Modbus::TModbusTCPTraits::ResetTransactionId(port);
2✔
176
    Modbus::TModbusTCPTraits traits;
2✔
177
    std::chrono::milliseconds t(10);
2✔
178

179
    std::vector<uint8_t> req = {7, 8, 9};
2✔
180
    ASSERT_THROW(traits.Transaction(port, 100, req, 2, t, t), TResponseTimeoutException);
2✔
181
}
182

183
TEST_F(TModbusTCPTraitsTest, IncrementTransactionId)
4✔
184
{
185
    std::vector<uint8_t> r = {0, 1, 0, 0, 0, 3, 100, 17, 18, 0, 2, 0, 0, 0, 3, 100, 19, 20};
1✔
186
    TPortMock port(r);
1✔
187
    Modbus::TModbusTCPTraits::ResetTransactionId(port);
1✔
188
    Modbus::TModbusTCPTraits traits;
1✔
189
    std::chrono::milliseconds t(10);
1✔
190

191
    std::vector<uint8_t> req = {7, 8, 9};
1✔
192
    auto resp = traits.Transaction(port, 100, req, 2, t, t).Pdu;
1✔
193
    ASSERT_EQ(resp.size(), 2);
1✔
194
    TestEqual(resp, {17, 18});
1✔
195
    ASSERT_EQ(port.GetLastRequest()[0], 0);
1✔
196
    ASSERT_EQ(port.GetLastRequest()[1], 1);
1✔
197

198
    Modbus::TModbusTCPTraits traits2;
1✔
199
    req.assign({10, 11, 12});
1✔
200
    resp = traits2.Transaction(port, 100, req, 2, t, t).Pdu;
1✔
201
    ASSERT_EQ(resp.size(), 2);
1✔
202
    TestEqual(resp, {19, 20});
1✔
203
    ASSERT_EQ(port.GetLastRequest()[0], 0);
1✔
204
    ASSERT_EQ(port.GetLastRequest()[1], 2);
1✔
205
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc