Skip to content

Commit 12a41c8

Browse files
committed
Extend DirCon loopback test with telemetry checks and push trigger
1 parent f1bdf12 commit 12a41c8

4 files changed

Lines changed: 130 additions & 0 deletions

File tree

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: DirCon loopback integration test
2+
3+
on:
4+
pull_request:
5+
push:
6+
workflow_dispatch:
7+
8+
jobs:
9+
linux-dircon-loopback:
10+
runs-on: ubuntu-24.04
11+
steps:
12+
- uses: actions/checkout@v4
13+
14+
- name: Install Qt dependencies
15+
run: |
16+
sudo apt update -y
17+
sudo apt-get install -y \
18+
qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools \
19+
qtquickcontrols2-5-dev qtconnectivity5-dev qtpositioning5-dev \
20+
libqt5bluetooth5 libqt5widgets5 libqt5positioning5 libqt5xml5 \
21+
libqt5charts5-dev libqt5charts5 libqt5networkauth5-dev \
22+
libqt5websockets5 libqt5websockets5-dev \
23+
libqt5sql5-sqlite libqt5sql5 libqt5sql5-mysql libqt5sql5-psql \
24+
libxcb-randr0-dev libxcb-xtest0-dev libxcb-xinerama0-dev \
25+
libxcb-shape0-dev libxcb-xkb-dev
26+
27+
- name: Build qdomyos-zwift static library
28+
run: |
29+
cd src
30+
qmake
31+
make -j"$(nproc)"
32+
33+
- name: Build test binary
34+
run: |
35+
cd tst
36+
qmake
37+
make -j"$(nproc)"
38+
39+
- name: Run DirCon loopback test (fakebike server -> dircon client)
40+
run: |
41+
cd tst
42+
./qdomyos-zwift-tests --gtest_filter=DirconLoopbackTestSuite.*
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#include "dirconloopbacktestsuite.h"
2+
3+
#include <QCoreApplication>
4+
#include <QDateTime>
5+
#include <QEventLoop>
6+
#include <QSettings>
7+
#include <functional>
8+
9+
#include "Tools/testsettings.h"
10+
#include "devices/dircon/dirconmanager.h"
11+
#include "devices/dircon/wahoodirconbike.h"
12+
#include "devices/fakebike/fakebike.h"
13+
#include "qzsettings.h"
14+
15+
namespace {
16+
17+
bool waitForCondition(const std::function<bool()> &predicate, int timeoutMs) {
18+
const QDateTime endTime = QDateTime::currentDateTime().addMSecs(timeoutMs);
19+
while (QDateTime::currentDateTime() < endTime) {
20+
if (predicate()) {
21+
return true;
22+
}
23+
QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
24+
}
25+
return predicate();
26+
}
27+
28+
} // namespace
29+
30+
void DirconLoopbackTestSuite::test_fakebike_dircon_server_accepts_wahoodirconbike_client() {
31+
TestSettings testSettings(QStringLiteral("qz-test-org"), QStringLiteral("qz-test-dircon-loopback"));
32+
testSettings.activate();
33+
34+
constexpr int kServerBasePort = 46000;
35+
testSettings.qsettings.setValue(QZSettings::dircon_yes, true);
36+
testSettings.qsettings.setValue(QZSettings::dircon_server_base_port, kServerBasePort);
37+
testSettings.qsettings.setValue(QZSettings::dircon_id, 1);
38+
testSettings.qsettings.setValue(QZSettings::virtual_device_enabled, false);
39+
testSettings.qsettings.setValue(QZSettings::zwift_play_emulator, false);
40+
testSettings.qsettings.setValue(QZSettings::rouvy_compatibility, false);
41+
42+
fakebike serverBike(true, true, true);
43+
DirconManager dirconServer(&serverBike, 4, 1.0);
44+
45+
DirconDeviceInfo deviceInfo;
46+
deviceInfo.name = QStringLiteral("Wahoo KICKR 0001");
47+
deviceInfo.displayName = QStringLiteral("Wahoo KICKR 0001 (DirCon)");
48+
deviceInfo.address = QStringLiteral("127.0.0.1");
49+
deviceInfo.port = static_cast<quint16>(kServerBasePort);
50+
51+
wahoodirconbike clientBike(deviceInfo, true, true, 4, 1.0);
52+
53+
const bool connected = waitForCondition([&clientBike]() { return clientBike.connected(); }, 5000);
54+
EXPECT_TRUE(connected) << "DirCon client failed to complete handshake against local fakebike DirCon server";
55+
56+
// Drive the fakebike with target power to force metric updates on the DirCon server side,
57+
// then verify the client receives non-zero telemetry through notifications.
58+
serverBike.changePower(180);
59+
60+
const bool receivedTelemetry = waitForCondition(
61+
[&clientBike]() {
62+
return clientBike.wattsMetric().value() > 0 &&
63+
clientBike.currentCadence().value() > 0 &&
64+
clientBike.currentSpeed().value() > 0;
65+
},
66+
8000);
67+
EXPECT_TRUE(receivedTelemetry)
68+
<< "DirCon client connected but did not receive expected bike telemetry (watt/cadence/speed)";
69+
70+
testSettings.deactivate();
71+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#ifndef DIRCONLOOPBACKTESTSUITE_H
2+
#define DIRCONLOOPBACKTESTSUITE_H
3+
4+
#include "gtest/gtest.h"
5+
6+
class DirconLoopbackTestSuite : public testing::Test {
7+
public:
8+
void test_fakebike_dircon_server_accepts_wahoodirconbike_client();
9+
};
10+
11+
TEST_F(DirconLoopbackTestSuite, FakeBikeDirconServerAcceptsWahooDirconBikeClient) {
12+
this->test_fakebike_dircon_server_accepts_wahoodirconbike_client();
13+
}
14+
15+
#endif // DIRCONLOOPBACKTESTSUITE_H

tst/qdomyos-zwift-tests.pro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ SOURCES += \
1616
Devices/bluetoothdevicetestsuite.cpp \
1717
Devices/bluetoothsignalreceiver.cpp \
1818
Devices/devicediscoveryinfo.cpp \
19+
Devices/dirconloopbacktestsuite.cpp \
1920
Devices/deviceindex.cpp \
2021
Devices/devicenamepatterngroup.cpp \
2122
Devices/devicetestdataindex.cpp \
@@ -50,6 +51,7 @@ HEADERS += \
5051
Devices/bluetoothdevicetestsuite.h \
5152
Devices/bluetoothsignalreceiver.h \
5253
Devices/devicediscoveryinfo.h \
54+
Devices/dirconloopbacktestsuite.h \
5355
Devices/deviceindex.h \
5456
Devices/devicenamepatterngroup.h \
5557
Devices/devicetestdataindex.h \

0 commit comments

Comments
 (0)