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

wirenboard / wb-mqtt-serial / 6

13 Jan 2026 06:31AM UTC coverage: 76.817% (+4.0%) from 72.836%
6

Pull #1049

github

8b2ffc
Ilia1S
Remove fw from groups
Pull Request #1049: WB-MR templates: Add delays

6873 of 9161 branches covered (75.02%)

12966 of 16879 relevant lines covered (76.82%)

830.18 hits per line

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

93.79
/test/fake_serial_device.cpp
1
#include "fake_serial_device.h"
2
#include "fake_serial_port.h"
3

4
using namespace std;
5

6
namespace // utility
7
{
8
    uint64_t GetValue(uint16_t* src, int width)
326✔
9
    {
10
        uint64_t res = 0;
326✔
11
        for (int i = 0; i < width; ++i) {
840✔
12
            auto bitCount = ((width - i) - 1) * 16;
514✔
13
            res |= uint64_t(src[i]) << bitCount;
514✔
14
        }
15
        return res;
326✔
16
    }
17

18
    void SetValue(uint16_t* dst, int width, uint64_t value)
108✔
19
    {
20
        for (int p = width - 1; p >= 0; --p) {
264✔
21
            dst[p] = value & 0xffff;
156✔
22
            value >>= 16;
156✔
23
        }
24
    }
108✔
25

26
    class TFakeRegisterRange: public TRegisterRange
27
    {
28
    public:
29
        TFakeRegisterRange()
172✔
30
        {}
172✔
31

32
        bool Add(TPort& port, PRegister reg, std::chrono::milliseconds pollLimit) override
400✔
33
        {
34
            if (HasOtherDeviceAndType(reg)) {
400✔
35
                return false;
×
36
            }
37
            RegisterList().push_back(reg);
400✔
38
            return true;
400✔
39
        }
40
    };
41

42
}; // utility
43

44
std::list<TFakeSerialDevice*> TFakeSerialDevice::Devices;
45

46
void TFakeSerialDevice::Register(TSerialDeviceFactory& factory)
142✔
47
{
48
    factory.RegisterProtocol(
142✔
49
        new TUint32SlaveIdProtocol("fake", TRegisterTypes({{TFakeSerialDevice::REG_FAKE, "fake", "text", U16}})),
426✔
50
        new TBasicDeviceFactory<TFakeSerialDevice>("#/definitions/simple_device_with_setup",
51
                                                   "#/definitions/common_channel"));
284✔
52
}
142✔
53

54
TFakeSerialDevice::TFakeSerialDevice(PDeviceConfig config, PProtocol protocol)
147✔
55
    : TSerialDevice(config, protocol),
56
      TUInt32SlaveId(config->SlaveId),
294✔
57
      Connected(true),
58
      SessionLogEnabled(false)
147✔
59
{
60
    Devices.push_back(this);
147✔
61
}
147✔
62

63
TRegisterValue TFakeSerialDevice::ReadRegisterImpl(TPort& port, const TRegisterConfig& reg)
376✔
64
{
65
    CheckFakePort();
376✔
66
    try {
67
        if (!FakePort->IsOpen()) {
376✔
68
            throw TSerialDeviceException("port not open");
×
69
        }
70

71
        if (!Connected) {
376✔
72
            throw TSerialDeviceTransientErrorException("device disconnected");
33✔
73
        }
74

75
        auto addr = GetUint32RegisterAddress(reg.GetAddress());
343✔
76

77
        if (Blockings[addr].first) {
343✔
78
            throw TSerialDeviceTransientErrorException("read blocked");
13✔
79
        }
80

81
        if (addr < 0 || addr > 256) {
330✔
82
            throw runtime_error("invalid register address");
×
83
        }
84

85
        if (reg.Type != REG_FAKE) {
330✔
86
            throw runtime_error("invalid register type");
×
87
        }
88

89
        TRegisterValue value;
660✔
90
        if (reg.IsString()) {
330✔
91
            std::string str;
8✔
92
            for (uint32_t i = 0; i < reg.Get16BitWidth(); ++i) {
132✔
93
                auto ch = static_cast<char>(Registers[addr + i]);
128✔
94
                if (ch != '\0') {
128✔
95
                    str.push_back(ch);
29✔
96
                }
97
            }
98
            value.Set(str);
4✔
99
        } else {
100
            value.Set(GetValue(&Registers[addr], reg.Get16BitWidth()));
326✔
101
        }
102

103
        FakePort->GetFixture().Emit() << "fake_serial_device '" << SlaveId << "': read address '" << reg.GetAddress()
660✔
104
                                      << "' value '" << value << "'";
330✔
105
        return value;
660✔
106
    } catch (const exception& e) {
92✔
107
        FakePort->GetFixture().Emit() << "fake_serial_device '" << SlaveId << "': read address '" << reg.GetAddress()
46✔
108
                                      << "' failed: '" << e.what() << "'";
46✔
109

110
        throw;
46✔
111
    }
112
}
113

114
void TFakeSerialDevice::WriteRegisterImpl(TPort& port, const TRegisterConfig& reg, const TRegisterValue& value)
124✔
115
{
116
    CheckFakePort();
124✔
117
    try {
118
        if (!FakePort->IsOpen()) {
124✔
119
            throw TSerialDeviceException("port not open");
×
120
        }
121

122
        if (!Connected) {
124✔
123
            throw TSerialDeviceTransientErrorException("device disconnected");
5✔
124
        }
125

126
        auto addr = GetUint32RegisterAddress(reg.GetAddress());
119✔
127

128
        if (Blockings[addr].second) {
119✔
129
            throw TSerialDeviceTransientErrorException("write blocked");
10✔
130
        }
131

132
        if (addr < 0 || addr > 256) {
109✔
133
            throw runtime_error("invalid register address");
×
134
        }
135

136
        if (reg.Type != REG_FAKE) {
109✔
137
            throw runtime_error("invalid register type");
×
138
        }
139

140
        if (reg.IsString()) {
109✔
141
            auto str = value.Get<std::string>();
2✔
142
            for (uint32_t i = 0; i < reg.Get16BitWidth(); ++i) {
33✔
143
                Registers[addr + i] = i < str.size() ? str[i] : 0;
32✔
144
            }
145
        } else {
146
            SetValue(&Registers[addr], reg.Get16BitWidth(), value.Get<uint64_t>());
108✔
147
        }
148
        FakePort->GetFixture().Emit() << "fake_serial_device '" << SlaveId << "': write to address '"
218✔
149
                                      << reg.GetAddress() << "' value '" << value << "'";
109✔
150

151
    } catch (const exception& e) {
30✔
152
        FakePort->GetFixture().Emit() << "fake_serial_device '" << SlaveId << "': write address '" << reg.GetAddress()
15✔
153
                                      << "' failed: '" << e.what() << "'";
15✔
154

155
        throw;
15✔
156
    }
157
}
109✔
158

159
void TFakeSerialDevice::SetTransferResult(bool ok)
488✔
160
{
161
    CheckFakePort();
488✔
162
    auto initialConnectionState = GetConnectionState();
488✔
163
    if ((initialConnectionState != TDeviceConnectionState::CONNECTED) && ok) {
488✔
164
        FakePort->GetFixture().Emit() << "fake_serial_device '" << SlaveId << "': transfer OK";
47✔
165
    }
166
    if (!ok) {
488✔
167
        FakePort->GetFixture().Emit() << "fake_serial_device '" << SlaveId << "': transfer FAIL";
69✔
168
    }
169

170
    TSerialDevice::SetTransferResult(ok);
488✔
171

172
    if (initialConnectionState != GetConnectionState()) {
488✔
173
        if (GetConnectionState() == TDeviceConnectionState::CONNECTED) {
57✔
174
            FakePort->GetFixture().Emit() << "fake_serial_device '" << SlaveId << "': reconnected";
47✔
175
        } else {
176
            FakePort->GetFixture().Emit() << "fake_serial_device '" << SlaveId << "': disconnected";
10✔
177
        }
178
    }
179
}
488✔
180

181
void TFakeSerialDevice::BlockReadFor(int addr, bool block)
8✔
182
{
183
    CheckFakePort();
8✔
184
    Blockings[addr].first = block;
8✔
185
    FakePort->GetFixture().Emit() << "fake_serial_device: " << (block ? "block" : "unblock") << " address '" << addr
16✔
186
                                  << "' for reading";
8✔
187
}
8✔
188

189
void TFakeSerialDevice::BlockWriteFor(int addr, bool block)
16✔
190
{
191
    CheckFakePort();
16✔
192
    Blockings[addr].second = block;
16✔
193
    FakePort->GetFixture().Emit() << "fake_serial_device: " << (block ? "block" : "unblock") << " address '" << addr
32✔
194
                                  << "' for writing";
16✔
195
}
16✔
196

197
uint32_t TFakeSerialDevice::Read2Registers(int addr)
9✔
198
{
199
    return (uint32_t(Registers[addr]) << 16) | Registers[addr + 1];
9✔
200
}
201

202
void TFakeSerialDevice::SetIsConnected(bool connected)
12✔
203
{
204
    Connected = connected;
12✔
205
}
12✔
206

207
TFakeSerialDevice::~TFakeSerialDevice()
238✔
208
{
209
    Devices.erase(std::remove(Devices.begin(), Devices.end(), this), Devices.end());
238✔
210
}
211

212
TFakeSerialDevice* TFakeSerialDevice::GetDevice(const std::string& slaveId)
24✔
213
{
214
    for (auto device: Devices) {
72✔
215
        if (device->DeviceConfig()->SlaveId == slaveId) {
72✔
216
            return device;
24✔
217
        }
218
    }
219
    return nullptr;
×
220
}
221

222
void TFakeSerialDevice::ClearDevices()
43✔
223
{
224
    Devices.clear();
43✔
225
}
43✔
226

227
PRegisterRange TFakeSerialDevice::CreateRegisterRange() const
172✔
228
{
229
    return std::make_shared<TFakeRegisterRange>();
172✔
230
}
231

232
void TFakeSerialDevice::SetSessionLogEnabled(bool enabled)
1✔
233
{
234
    SessionLogEnabled = enabled;
1✔
235
}
1✔
236

237
void TFakeSerialDevice::PrepareImpl(TPort& port)
68✔
238
{
239
    CheckFakePort();
68✔
240
    TSerialDevice::PrepareImpl(port);
68✔
241
    if (SessionLogEnabled) {
68✔
242
        FakePort->GetFixture().Emit() << "fake_serial_device '" << SlaveId << "': prepare";
4✔
243
    }
244
}
68✔
245

246
void TFakeSerialDevice::EndSession(TPort& port)
14✔
247
{
248
    CheckFakePort();
14✔
249
    if (SessionLogEnabled) {
14✔
250
        FakePort->GetFixture().Emit() << "fake_serial_device '" << SlaveId << "': end session";
3✔
251
    }
252
}
14✔
253

254
void TFakeSerialDevice::SetFakePort(PFakeSerialPort fakePort)
147✔
255
{
256
    FakePort = fakePort;
147✔
257
}
147✔
258

259
void TFakeSerialDevice::CheckFakePort() const
1,094✔
260
{
261
    if (!FakePort) {
1,094✔
262
        throw runtime_error("not fake serial port passed to fake serial device");
×
263
    }
264
}
1,094✔
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