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

wirenboard / wb-mqtt-serial / 2

29 Dec 2025 12:28PM UTC coverage: 76.817% (+4.0%) from 72.836%
2

Pull #1045

github

54aa0c
pgasheev
up changelog
Pull Request #1045: Fix firmware version in WB-M1W2 template

6873 of 9161 branches covered (75.02%)

12966 of 16879 relevant lines covered (76.82%)

1651.61 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)
652✔
9
    {
10
        uint64_t res = 0;
652✔
11
        for (int i = 0; i < width; ++i) {
1,680✔
12
            auto bitCount = ((width - i) - 1) * 16;
1,028✔
13
            res |= uint64_t(src[i]) << bitCount;
1,028✔
14
        }
15
        return res;
652✔
16
    }
17

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

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

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

42
}; // utility
43

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

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

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

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

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

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

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

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

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

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

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

110
        throw;
92✔
111
    }
112
}
113

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

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

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

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

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

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

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

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

155
        throw;
30✔
156
    }
157
}
218✔
158

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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