diff --git a/tst/Devices/ApexBike/apexbiketestdata.h b/tst/Devices/ApexBike/apexbiketestdata.h index b37e1edb05..390fb71476 100644 --- a/tst/Devices/ApexBike/apexbiketestdata.h +++ b/tst/Devices/ApexBike/apexbiketestdata.h @@ -1,10 +1,13 @@ #pragma once -#include "Devices/Bike/biketestdata.h".h" +#include "Devices/Bike/biketestdata.h" #include "devices/apexbike/apexbike.h" class ApexBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new apexbike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } public: ApexBikeTestData() : BikeTestData("Apex Bike") { this->addDeviceName("WLT8266BM", comparison::StartsWithIgnoreCase); diff --git a/tst/Devices/Bike/biketestdata.h b/tst/Devices/Bike/biketestdata.h index ffaea95201..333ec6c46c 100644 --- a/tst/Devices/Bike/biketestdata.h +++ b/tst/Devices/Bike/biketestdata.h @@ -3,7 +3,21 @@ #include "Devices/bluetoothdevicetestdata.h" #include "devices/bike.h" +class BikeOptions { +public: + double resistanceGain=1.0, resistanceOffset=0.0; + bool noResistance=false, noHeartService = false, noVirtualDevice = false; + +}; + class BikeTestData : public BluetoothDeviceTestData { +protected: + /** + * @brief Template function called from createInstance to create an instance of the device class. + * @param options + * @return + */ + virtual bike* doCreateInstance(const BikeOptions& options) =0; public: BikeTestData(std::string deviceName) : BluetoothDeviceTestData(deviceName) {} @@ -15,5 +29,18 @@ class BikeTestData : public BluetoothDeviceTestData { bool get_isExpectedDevice(bluetoothdevice * detectedDevice) const override { return dynamic_cast(detectedDevice)!=nullptr; } + + /** + * @brief (Potentially amongst other things) Calls a protected function to create an instance of the device class. + * @param options + * @return + */ + bike* createInstance(const BikeOptions& options) { + // potentially validate or alter the options + auto result = this->doCreateInstance(options); + + // potentially adjust the device object (e.g. connect signals and slots) + return result; + } }; diff --git a/tst/Devices/BkoolBike/bkoolbiketestdata.h b/tst/Devices/BkoolBike/bkoolbiketestdata.h index 96f7163d59..c1bfc335cf 100644 --- a/tst/Devices/BkoolBike/bkoolbiketestdata.h +++ b/tst/Devices/BkoolBike/bkoolbiketestdata.h @@ -1,12 +1,15 @@ #pragma once -#include "Devices/bluetoothdevicetestdata.h" +#include "Devices/Bike/biketestdata.h" #include "devices/bkoolbike/bkoolbike.h" -class BkoolBikeTestData : public BluetoothDeviceTestData { - +class BkoolBikeTestData : public BikeTestData { +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new bkoolbike(options.noResistance, options.noHeartService); + } public: - BkoolBikeTestData() : BluetoothDeviceTestData("Bkool Bike") { + BkoolBikeTestData() : BikeTestData("Bkool Bike") { this->addDeviceName("BKOOLSMARTPRO", comparison::StartsWithIgnoreCase); } diff --git a/tst/Devices/CSCBike/cscbiketestdata.h b/tst/Devices/CSCBike/cscbiketestdata.h index c24db03dfe..abdaa1265a 100644 --- a/tst/Devices/CSCBike/cscbiketestdata.h +++ b/tst/Devices/CSCBike/cscbiketestdata.h @@ -6,6 +6,11 @@ class CSCBikeTestData : public BikeTestData { protected: QString cscBikeName; + + + bike* doCreateInstance(const BikeOptions& options) override { + return new cscbike(options.noResistance, options.noHeartService, options.noVirtualDevice); + } public: CSCBikeTestData(std::string testName) : BikeTestData(testName) { this->cscBikeName = "CyclingSpeedCadenceBike-"; diff --git a/tst/Devices/Chronobike/chronobiketestdata.h b/tst/Devices/Chronobike/chronobiketestdata.h index 40fe1f3ac0..a43cda3bb3 100644 --- a/tst/Devices/Chronobike/chronobiketestdata.h +++ b/tst/Devices/Chronobike/chronobiketestdata.h @@ -4,7 +4,10 @@ #include "devices/chronobike/chronobike.h" class ChronobikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new chronobike(options.noResistance, options.noHeartService); + } public: ChronobikeTestData() : BikeTestData("Chronobike") { this->addDeviceName("CHRONO ", comparison::StartsWithIgnoreCase); diff --git a/tst/Devices/CompuTrainer/computrainertestdata.h b/tst/Devices/CompuTrainer/computrainertestdata.h index a93f537cad..b6d64c1160 100644 --- a/tst/Devices/CompuTrainer/computrainertestdata.h +++ b/tst/Devices/CompuTrainer/computrainertestdata.h @@ -5,6 +5,10 @@ class CompuTrainerTestData : public BikeTestData { protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new computrainerbike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } + bool configureSettings(DeviceDiscoveryInfo& info, bool enable) const override { info.computrainer_serial_port = enable ? "X":QString(); return true; diff --git a/tst/Devices/DomyosBike/domyosbiketestdata.h b/tst/Devices/DomyosBike/domyosbiketestdata.h index ba91cc8e87..0317653314 100644 --- a/tst/Devices/DomyosBike/domyosbiketestdata.h +++ b/tst/Devices/DomyosBike/domyosbiketestdata.h @@ -4,7 +4,10 @@ #include "devices/domyosbike/domyosbike.h" class DomyosBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new domyosbike(options.noResistance, options.noHeartService, false, options.resistanceOffset, options.resistanceGain); + } public: DomyosBikeTestData() : BikeTestData("Domyos Bike") { diff --git a/tst/Devices/EchelonConnectSportBike/echelonconnectsportbiketestdata.h b/tst/Devices/EchelonConnectSportBike/echelonconnectsportbiketestdata.h index 9e08797ff1..2ff101dded 100644 --- a/tst/Devices/EchelonConnectSportBike/echelonconnectsportbiketestdata.h +++ b/tst/Devices/EchelonConnectSportBike/echelonconnectsportbiketestdata.h @@ -6,7 +6,10 @@ #include "devices/echelonconnectsport/echelonconnectsport.h" class EchelonConnectSportBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new echelonconnectsport(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } public: EchelonConnectSportBikeTestData() : BikeTestData("Echelon Connect Sport Bike") { this->addDeviceName("ECH", comparison::StartsWith); diff --git a/tst/Devices/FTMSBike/ftmsbiketestdata.cpp b/tst/Devices/FTMSBike/ftmsbiketestdata.cpp index 1fcfa56194..bbb8c94699 100644 --- a/tst/Devices/FTMSBike/ftmsbiketestdata.cpp +++ b/tst/Devices/FTMSBike/ftmsbiketestdata.cpp @@ -1,5 +1,9 @@ #include "ftmsbiketestdata.h" +#include "Devices/SnodeBike/snodebiketestdata.h" +#include "Devices/FitPlusBike/fitplusbiketestdata.h" +#include "Devices/StagesBike/stagesbiketestdata.h" + void FTMSBikeTestData::configureExclusions() { this->exclude(new SnodeBike1TestData()); this->exclude(new SnodeBike2TestData()); diff --git a/tst/Devices/FTMSBike/ftmsbiketestdata.h b/tst/Devices/FTMSBike/ftmsbiketestdata.h index 2c23b42448..4ab9888410 100644 --- a/tst/Devices/FTMSBike/ftmsbiketestdata.h +++ b/tst/Devices/FTMSBike/ftmsbiketestdata.h @@ -7,12 +7,12 @@ #include "devices/ftmsbike/ftmsbike.h" -#include "Devices/SnodeBike/snodebiketestdata.h" -#include "Devices/FitPlusBike/fitplusbiketestdata.h" -#include "Devices/StagesBike/stagesbiketestdata.h" class FTMSBikeTestData : public BikeTestData { protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new ftmsbike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } void configureExclusions() override; FTMSBikeTestData(std::string testName) : BikeTestData(testName) { diff --git a/tst/Devices/FakeBike/fakebiketestdata.h b/tst/Devices/FakeBike/fakebiketestdata.h index 2679adb69b..cb13a9ff36 100644 --- a/tst/Devices/FakeBike/fakebiketestdata.h +++ b/tst/Devices/FakeBike/fakebiketestdata.h @@ -9,6 +9,10 @@ class FakeBikeTestData : public BikeTestData { protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new fakebike(options.noResistance, options.noHeartService, options.noVirtualDevice); + } + bool configureSettings(DeviceDiscoveryInfo& info, bool enable) const override { info.fake_bike = enable; return true; diff --git a/tst/Devices/FitPlusBike/fitplusbiketestdata.h b/tst/Devices/FitPlusBike/fitplusbiketestdata.h index 38668f0361..266c25d46f 100644 --- a/tst/Devices/FitPlusBike/fitplusbiketestdata.h +++ b/tst/Devices/FitPlusBike/fitplusbiketestdata.h @@ -9,6 +9,10 @@ class FitPlusBikeFSTestData : public BikeTestData { protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new fitplusbike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } + bool configureSettings(DeviceDiscoveryInfo& info, bool enable) const override { info.fitplus_bike = enable; return true; @@ -27,7 +31,10 @@ class FitPlusBikeFSTestData : public BikeTestData { }; class FitPlusBikeMRKTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new fitplusbike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } public: FitPlusBikeMRKTestData() : BikeTestData("FitPlus Bike (MRK, no settings)"){ diff --git a/tst/Devices/FlywheelBike/flywheelbiketestdata.h b/tst/Devices/FlywheelBike/flywheelbiketestdata.h index fd049195fe..1660ae3d2e 100644 --- a/tst/Devices/FlywheelBike/flywheelbiketestdata.h +++ b/tst/Devices/FlywheelBike/flywheelbiketestdata.h @@ -10,6 +10,9 @@ class FlywheelBikeTestData : public BikeTestData { protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new flywheelbike(options.noResistance, options.noHeartService); + } FlywheelBikeTestData(std::string testName) : BikeTestData(testName) { } public: diff --git a/tst/Devices/HorizonGR7Bike/horizongr7biketestdata.h b/tst/Devices/HorizonGR7Bike/horizongr7biketestdata.h index 540ca42b64..f597feb040 100644 --- a/tst/Devices/HorizonGR7Bike/horizongr7biketestdata.h +++ b/tst/Devices/HorizonGR7Bike/horizongr7biketestdata.h @@ -7,7 +7,10 @@ class HorizonGR7BikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new horizongr7bike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } public: HorizonGR7BikeTestData() : BikeTestData("Horizon GR7 Bike") { this->addDeviceName("JFIC", comparison::StartsWithIgnoreCase); diff --git a/tst/Devices/InspireBike/inspirebiketestdata.h b/tst/Devices/InspireBike/inspirebiketestdata.h index b1156f430d..cd00605533 100644 --- a/tst/Devices/InspireBike/inspirebiketestdata.h +++ b/tst/Devices/InspireBike/inspirebiketestdata.h @@ -6,7 +6,10 @@ class InspireBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new inspirebike(options.noResistance, options.noHeartService); + } public: InspireBikeTestData() : BikeTestData("Inspire Bike") { this->addDeviceName("IC", comparison::StartsWithIgnoreCase, 8); diff --git a/tst/Devices/KeepBike/keepbiketestdata.h b/tst/Devices/KeepBike/keepbiketestdata.h index 22229f1845..bb7a77dabb 100644 --- a/tst/Devices/KeepBike/keepbiketestdata.h +++ b/tst/Devices/KeepBike/keepbiketestdata.h @@ -8,7 +8,10 @@ class KeepBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new keepbike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } public: KeepBikeTestData() : BikeTestData("Keep Bike") { this->addDeviceName("KEEP_BIKE_", comparison::StartsWithIgnoreCase); diff --git a/tst/Devices/M3IBike/m3ibiketestdata.h b/tst/Devices/M3IBike/m3ibiketestdata.h index 30d322b4eb..f86431395f 100644 --- a/tst/Devices/M3IBike/m3ibiketestdata.h +++ b/tst/Devices/M3IBike/m3ibiketestdata.h @@ -11,6 +11,9 @@ class M3IBikeTestData : public BikeTestData { protected: void configureBluetoothDeviceInfos(const QBluetoothDeviceInfo& info, bool enable, std::vector& bluetoothDeviceInfos) const override; + bike* doCreateInstance(const BikeOptions& options) override { + return new m3ibike(options.noResistance, options.noHeartService); + } public: M3IBikeTestData() : BikeTestData("M3I Bike") { this->addDeviceName("M3", comparison::StartsWith); diff --git a/tst/Devices/MCFBike/mcfbiketestdata.h b/tst/Devices/MCFBike/mcfbiketestdata.h index 6ad1403077..bd26bf1000 100644 --- a/tst/Devices/MCFBike/mcfbiketestdata.h +++ b/tst/Devices/MCFBike/mcfbiketestdata.h @@ -8,7 +8,10 @@ class MCFBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new mcfbike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } public: MCFBikeTestData() : BikeTestData("MCF Bike") { this->addDeviceName("MCF-", comparison::StartsWithIgnoreCase); diff --git a/tst/Devices/MepanelBike/mepanelbiketestdata.h b/tst/Devices/MepanelBike/mepanelbiketestdata.h index 526773cc54..7636332582 100644 --- a/tst/Devices/MepanelBike/mepanelbiketestdata.h +++ b/tst/Devices/MepanelBike/mepanelbiketestdata.h @@ -9,7 +9,10 @@ class MepanelBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new mepanelbike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } public: MepanelBikeTestData() : BikeTestData("Mepanel Bike") { this->addDeviceName("MEPANEL", comparison::StartsWithIgnoreCase); diff --git a/tst/Devices/NPECableBike/npecablebiketestdata.h b/tst/Devices/NPECableBike/npecablebiketestdata.h index 00911091ea..cf4168d4c7 100644 --- a/tst/Devices/NPECableBike/npecablebiketestdata.h +++ b/tst/Devices/NPECableBike/npecablebiketestdata.h @@ -8,6 +8,9 @@ class NPECableBikeTestData : public BikeTestData { protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new npecablebike(options.noResistance, options.noHeartService); + } NPECableBikeTestData(std::string testName) : BikeTestData(testName) {} public: deviceType get_expectedDeviceType() const override { return deviceType::NPECableBike; } diff --git a/tst/Devices/NautilusBike/nautilusbiketestdata.h b/tst/Devices/NautilusBike/nautilusbiketestdata.h index ca971c835b..f5d3761740 100644 --- a/tst/Devices/NautilusBike/nautilusbiketestdata.h +++ b/tst/Devices/NautilusBike/nautilusbiketestdata.h @@ -6,7 +6,10 @@ class NautilusBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new nautilusbike(options.noResistance, options.noHeartService, false, options.resistanceOffset, options.resistanceGain); + } public: NautilusBikeTestData(): BikeTestData("Nautilus Bike") { this->addDeviceName("NAUTILUS B", comparison::StartsWithIgnoreCase); diff --git a/tst/Devices/PafersBike/pafersbiketestdata.h b/tst/Devices/PafersBike/pafersbiketestdata.h index fac76b18dd..7366dd3fd7 100644 --- a/tst/Devices/PafersBike/pafersbiketestdata.h +++ b/tst/Devices/PafersBike/pafersbiketestdata.h @@ -7,6 +7,9 @@ class PafersBikeTestData : public BikeTestData { protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new pafersbike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } bool configureSettings(DeviceDiscoveryInfo& info, bool enable) const override { // the treadmill is given priority info.pafers_treadmill = !enable; diff --git a/tst/Devices/ProFormBike/proformbiketestdata.h b/tst/Devices/ProFormBike/proformbiketestdata.h index db8f64eac0..39c7186b37 100644 --- a/tst/Devices/ProFormBike/proformbiketestdata.h +++ b/tst/Devices/ProFormBike/proformbiketestdata.h @@ -7,7 +7,10 @@ class ProFormBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new proformbike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } public: ProFormBikeTestData() : BikeTestData("ProForm Bike") { this->addDeviceName("I_EB", comparison::StartsWith); diff --git a/tst/Devices/ProFormWiFiBike/proformwifibiketestdata.h b/tst/Devices/ProFormWiFiBike/proformwifibiketestdata.h index 6211c167d3..07be0fb760 100644 --- a/tst/Devices/ProFormWiFiBike/proformwifibiketestdata.h +++ b/tst/Devices/ProFormWiFiBike/proformwifibiketestdata.h @@ -8,6 +8,10 @@ class ProFormWiFiBikeTestData : public BikeTestData { protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new proformwifibike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } + bool configureSettings(DeviceDiscoveryInfo& info, bool enable) const override { info.proformtdf4ip = enable ? this->get_testIP():QString(); return true; diff --git a/tst/Devices/RenphoBike/renphobiketestdata.cpp b/tst/Devices/RenphoBike/renphobiketestdata.cpp index d4960f3a13..be8f2f79d1 100644 --- a/tst/Devices/RenphoBike/renphobiketestdata.cpp +++ b/tst/Devices/RenphoBike/renphobiketestdata.cpp @@ -1,4 +1,6 @@ #include "renphobiketestdata.h" +#include "Devices/FitPlusBike/fitplusbiketestdata.h" +#include "Devices/SnodeBike/snodebiketestdata.h" void RenphoBikeTestData::configureExclusions() { this->exclude(new FitPlusBikeFSTestData()); diff --git a/tst/Devices/RenphoBike/renphobiketestdata.h b/tst/Devices/RenphoBike/renphobiketestdata.h index 8bc2254cec..23b61d83f0 100644 --- a/tst/Devices/RenphoBike/renphobiketestdata.h +++ b/tst/Devices/RenphoBike/renphobiketestdata.h @@ -1,13 +1,14 @@ #pragma once #include "Devices/Bike/biketestdata.h" -#include "Devices/FitPlusBike/fitplusbiketestdata.h" -#include "Devices/SnodeBike/snodebiketestdata.h" - #include "devices/renphobike/renphobike.h" class RenphoBikeTestData : public BikeTestData { protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new renphobike(options.noResistance, options.noHeartService); + } + RenphoBikeTestData(std::string testName) : BikeTestData(testName) { } diff --git a/tst/Devices/Schwinn170Bike/schwinn170biketestdata.h b/tst/Devices/Schwinn170Bike/schwinn170biketestdata.h index 3d64746ec4..4b30ea20d6 100644 --- a/tst/Devices/Schwinn170Bike/schwinn170biketestdata.h +++ b/tst/Devices/Schwinn170Bike/schwinn170biketestdata.h @@ -5,7 +5,10 @@ class Schwinn170BikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new schwinn170bike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } public: Schwinn170BikeTestData() : BikeTestData("Schwinn 170 Bike") { diff --git a/tst/Devices/SchwinnIC4Bike/schwinnic4biketestdata.h b/tst/Devices/SchwinnIC4Bike/schwinnic4biketestdata.h index 9dce840569..678e5d3481 100644 --- a/tst/Devices/SchwinnIC4Bike/schwinnic4biketestdata.h +++ b/tst/Devices/SchwinnIC4Bike/schwinnic4biketestdata.h @@ -6,7 +6,10 @@ class SchwinnIC4BikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new schwinnic4bike(options.noResistance, options.noHeartService); + } public: SchwinnIC4BikeTestData() : BikeTestData("Schwinn IC4 Bike") { diff --git a/tst/Devices/SkandikaWiryBike/skandikawirybiketestdata.h b/tst/Devices/SkandikaWiryBike/skandikawirybiketestdata.h index 41ee111ad4..81ca608f42 100644 --- a/tst/Devices/SkandikaWiryBike/skandikawirybiketestdata.h +++ b/tst/Devices/SkandikaWiryBike/skandikawirybiketestdata.h @@ -7,7 +7,10 @@ class SkandikaWiryBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new skandikawiribike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } public: SkandikaWiryBikeTestData() : BikeTestData("Skandika Wiry Bike") { this->addDeviceName("BFCP", comparison::StartsWithIgnoreCase); diff --git a/tst/Devices/SnodeBike/snodebiketestdata.h b/tst/Devices/SnodeBike/snodebiketestdata.h index f504cf141d..1b8a11959a 100644 --- a/tst/Devices/SnodeBike/snodebiketestdata.h +++ b/tst/Devices/SnodeBike/snodebiketestdata.h @@ -6,6 +6,9 @@ class SnodeBikeTestData : public BikeTestData { protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new snodebike(options.noResistance, options.noHeartService); + } SnodeBikeTestData(std::string testName) : BikeTestData(testName) { } void configureExclusions() override; diff --git a/tst/Devices/SoleBike/solebiketestdata.h b/tst/Devices/SoleBike/solebiketestdata.h index efca101f13..3cac78bc05 100644 --- a/tst/Devices/SoleBike/solebiketestdata.h +++ b/tst/Devices/SoleBike/solebiketestdata.h @@ -7,7 +7,10 @@ class SoleBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new solebike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } public: SoleBikeTestData() : BikeTestData("Sole Bike") { this->addDeviceName("LCB", comparison::StartsWithIgnoreCase); diff --git a/tst/Devices/SportsPlusBike/sportsplusbiketestdata.h b/tst/Devices/SportsPlusBike/sportsplusbiketestdata.h index 7e3746057c..b1d55ebaa7 100644 --- a/tst/Devices/SportsPlusBike/sportsplusbiketestdata.h +++ b/tst/Devices/SportsPlusBike/sportsplusbiketestdata.h @@ -7,7 +7,10 @@ class SportsPlusBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new sportsplusbike(options.noResistance, options.noHeartService); + } public: SportsPlusBikeTestData() : BikeTestData("Sports Plus Bike") { this->addDeviceName("CARDIOFIT", comparison::StartsWithIgnoreCase); diff --git a/tst/Devices/SportsTechBike/sportstechbiketestdata.h b/tst/Devices/SportsTechBike/sportstechbiketestdata.h index 7632a56ebf..a3fd488242 100644 --- a/tst/Devices/SportsTechBike/sportstechbiketestdata.h +++ b/tst/Devices/SportsTechBike/sportstechbiketestdata.h @@ -7,7 +7,10 @@ class SportsTechBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new sportstechbike(options.noResistance, options.noHeartService); + } public: SportsTechBikeTestData() : BikeTestData("Sport Tech Bike") { this->addDeviceName("EW-BK", comparison::StartsWithIgnoreCase); diff --git a/tst/Devices/StagesBike/stagesbiketestdata.h b/tst/Devices/StagesBike/stagesbiketestdata.h index 0939c8add4..3c4cb60227 100644 --- a/tst/Devices/StagesBike/stagesbiketestdata.h +++ b/tst/Devices/StagesBike/stagesbiketestdata.h @@ -5,6 +5,9 @@ class StagesBikeTestData : public BikeTestData { protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new stagesbike(options.noResistance, options.noHeartService, options.noVirtualDevice); + } StagesBikeTestData(std::string testName): BikeTestData(testName) { } diff --git a/tst/Devices/TacxNeo2/tacxneo2testdata.h b/tst/Devices/TacxNeo2/tacxneo2testdata.h index 1293272299..991cabdcc3 100644 --- a/tst/Devices/TacxNeo2/tacxneo2testdata.h +++ b/tst/Devices/TacxNeo2/tacxneo2testdata.h @@ -7,7 +7,10 @@ class TacxNeo2TestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new tacxneo2(options.noResistance, options.noHeartService); + } public: TacxNeo2TestData() : BikeTestData("Tacx Neo 2 Bike") { this->addDeviceName("TACX NEO", comparison::StartsWithIgnoreCase); diff --git a/tst/Devices/TrxAppGateUSBBike/trxappgateusbbiketestdata.h b/tst/Devices/TrxAppGateUSBBike/trxappgateusbbiketestdata.h index aba3940dec..0797e90f8a 100644 --- a/tst/Devices/TrxAppGateUSBBike/trxappgateusbbiketestdata.h +++ b/tst/Devices/TrxAppGateUSBBike/trxappgateusbbiketestdata.h @@ -6,6 +6,9 @@ class TrxAppGateUSBBikeTestData : public BikeTestData { protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new trxappgateusbbike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } TrxAppGateUSBBikeTestData(std::string testName) : BikeTestData(testName) { } diff --git a/tst/Devices/UltrasportBike/ultrasportbiketestdata.h b/tst/Devices/UltrasportBike/ultrasportbiketestdata.h index 762d849d8d..c89b57c33d 100644 --- a/tst/Devices/UltrasportBike/ultrasportbiketestdata.h +++ b/tst/Devices/UltrasportBike/ultrasportbiketestdata.h @@ -7,7 +7,10 @@ class UltrasportBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new ultrasportbike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } public: UltrasportBikeTestData() : BikeTestData("Ultrasport Bike") { this->addDeviceName("X-BIKE", comparison::StartsWithIgnoreCase); diff --git a/tst/Devices/WahooKickrSnapBike/wahookickrsnapbiketestdata.h b/tst/Devices/WahooKickrSnapBike/wahookickrsnapbiketestdata.h index c22a8c4377..78cd99133b 100644 --- a/tst/Devices/WahooKickrSnapBike/wahookickrsnapbiketestdata.h +++ b/tst/Devices/WahooKickrSnapBike/wahookickrsnapbiketestdata.h @@ -7,7 +7,10 @@ class WahooKickrSnapBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new wahookickrsnapbike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } public: WahooKickrSnapBikeTestData() : BikeTestData("Wahoo Kickr Snap Bike") { this->addDeviceName("KICKR SNAP", comparison::StartsWithIgnoreCase); diff --git a/tst/Devices/YesoulBike/yesoulbiketestdata.h b/tst/Devices/YesoulBike/yesoulbiketestdata.h index a63f353379..e903c3cb04 100644 --- a/tst/Devices/YesoulBike/yesoulbiketestdata.h +++ b/tst/Devices/YesoulBike/yesoulbiketestdata.h @@ -1,13 +1,13 @@ #pragma once - #include "Devices/Bike/biketestdata.h" - #include "devices/yesoulbike/yesoulbike.h" - class YesoulBikeTestData : public BikeTestData { - +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new yesoulbike(options.noResistance, options.noHeartService, options.resistanceOffset, options.resistanceGain); + } public: YesoulBikeTestData() : BikeTestData("Yesoul Bike") { this->addDeviceName(yesoulbike::bluetoothName, comparison::StartsWith); diff --git a/tst/Devices/biketestsuite.cpp b/tst/Devices/biketestsuite.cpp new file mode 100644 index 0000000000..b98e6534a6 --- /dev/null +++ b/tst/Devices/biketestsuite.cpp @@ -0,0 +1,173 @@ +#include "biketestsuite.h" +#include "ErgInterface/bikeergfunctions.h" + +template +BikeTestSuite::BikeTestSuite() : testSettings("Roberto Viola", "QDomyos-Zwift Testing") {} + +template +void BikeTestSuite::SetUp() { + BikeOptions options; + this->device =this->typeParam.createInstance(options); + this->ergInterface = new bikeergfunctions(this->device); + + this->maxRPM = this->ergInterface->getMaxCadence().value_or(120); + this->minRPM = this->ergInterface->getMinCadence().value_or(1); + this->maxResistance = this->ergInterface->getMaxResistance().value_or(255); + this->minResistance = this->ergInterface->getMinResistance().value_or(0); + +} + +template +void BikeTestSuite::TearDown() { + if(this->device) delete this->device; + if(this->ergInterface) delete this->ergInterface; + this->device = nullptr; + this->ergInterface = nullptr; +} + +template +void BikeTestSuite::test_powerFunctions_minResistance() { + const auto erg = this->ergInterface; + uint16_t p0, p1; + resistance_t r0, r1; + QStringList errors; + QString powerBeyondResistanceLimit = QStringLiteral("Power at C:%1 RPM not bounded at %6 resistance (R:%2, P:%3W), (R:%4, P:%5W)"); + + if(!erg->getMinResistance().has_value()) + { + GTEST_SKIP() << "No minimum resistance defined"; + } + + // traverse the cadence edges checking the power is clipped to the values for the max and min resistance + for(uint32_t cadenceRPM=minRPM; cadenceRPM<=maxRPM; cadenceRPM++) + { + r0 = minResistance; + r1 = minResistance-1; + p0 = erg->getPower(cadenceRPM, r0); + p1 = erg->getPower(cadenceRPM, r1); + + if(p0 != p1) + errors.append(powerBeyondResistanceLimit.arg(cadenceRPM).arg(r0).arg(p0).arg(r1).arg(p1).arg("minimum")); + } + + ASSERT_TRUE(errors.empty()) << errors.join('\n').toStdString(); +} + + +template +void BikeTestSuite::test_powerFunctions_maxResistance() { + const auto erg = this->ergInterface; + uint16_t p0, p1; + resistance_t r0, r1; + QStringList errors; + QString powerBeyondResistanceLimit = QStringLiteral("Power at C:%1 RPM not bounded at %6 resistance (R:%2, P:%3W), (R:%4, P:%5W)"); + + if(!erg->getMaxResistance().has_value()) + { + GTEST_SKIP() << "No maximum resistance defined."; + } + + // traverse the cadence edges checking the power is clipped to the values for the max and min resistance + for(uint32_t cadenceRPM=minRPM; cadenceRPM<=maxRPM; cadenceRPM++) + { + r0 = maxResistance; + r1 = maxResistance+1; + p0 = erg->getPower(cadenceRPM, r0); + p1 = erg->getPower(cadenceRPM, r1); + + if(p0 != p1) + errors.append(powerBeyondResistanceLimit.arg(cadenceRPM).arg(r0).arg(p0).arg(r1).arg(p1).arg("maximum")); + } + + ASSERT_TRUE(errors.empty()) << errors.join('\n').toStdString(); +} + +template +void BikeTestSuite::test_powerFunctions_minCadence() { + const auto erg = this->ergInterface; + uint16_t p0, p1; + QStringList errors; + + if(!erg->getMinCadence().has_value()) + { + GTEST_SKIP() << "No minimum cadence defined."; + } + + // traverse the resistance edge checking the power is clipped to the values for the max and min cadence + + QString powerBeyondCadenceLimit = QStringLiteral("Power at R:%1 not bounded at %6 cadence (C:%2 RPM, P:%3W), (C:%4 RPM, P:%5W)"); + + for(resistance_t r=minResistance; r<=maxResistance; r++) + { + const int32_t c0 = minRPM, c1=minRPM-1; + p0 = erg->getPower(c0, r); + p1 = erg->getPower(c1, r); + + if(p0!=p1) + errors.append(powerBeyondCadenceLimit.arg(r).arg(c0).arg(p0).arg(c1).arg(p1).arg("minimum")); + } + + ASSERT_TRUE(errors.empty()) << errors.join('\n').toStdString(); +} + +template +void BikeTestSuite::test_powerFunctions_maxCadence() { + const auto erg = this->ergInterface; + uint16_t p0, p1; + QStringList errors; + + if(!erg->getMaxCadence().has_value()) + { + GTEST_SKIP() << "No maximum cadence defined"; + } + + // traverse the resistance edge checking the power is clipped to the values for the max and min cadence + + QString powerBeyondCadenceLimit = QStringLiteral("Power at R:%1 not bounded at %6 cadence (C:%2 RPM, P:%3W), (C:%4 RPM, P:%5W)"); + + for(resistance_t r=minResistance; r<=maxResistance; r++) + { + const int32_t c0 = maxRPM, c1=maxRPM+1; + p0 = erg->getPower(c0, r); + p1 = erg->getPower(c1, r); + + if(p0!=p1) + errors.append(powerBeyondCadenceLimit.arg(r).arg(c0).arg(p0).arg(c1).arg(p1).arg("maximum")); + } + + ASSERT_TRUE(errors.empty()) << errors.join('\n').toStdString(); +} + +template +void BikeTestSuite::test_powerFunctions_resistancePowerConversion() { + const auto erg = this->ergInterface; + QStringList errors; + + // test inverses + QString unexpectedResistance=QStringLiteral("P(C:%3, R:%1)=%2 but R(C:%3, P:%2)=%4 and P(C:%3, R:%4)=%5"); + for(uint32_t cadenceRPM=minRPM; cadenceRPM<=maxRPM; cadenceRPM++) + { + uint16_t lastPower=0xFFFF; + for(resistance_t r=minResistance; r<=maxResistance; r++) + { + uint16_t power = erg->getPower(cadenceRPM, r); + + // if this resistance reaches a new power level, check the inverse + if(power!=lastPower) + { + lastPower = power; + resistance_t resistance = erg->getResistance(cadenceRPM, power); + + if(r!=resistance) { + uint16_t newPower = erg->getPower(cadenceRPM, resistance); + + errors.append(unexpectedResistance.arg(r).arg(power).arg(cadenceRPM).arg(resistance).arg(newPower)); + } + + } + + } + } + + ASSERT_TRUE(errors.empty()) << errors.join('\n').toStdString(); +} diff --git a/tst/Devices/biketestsuite.h b/tst/Devices/biketestsuite.h new file mode 100644 index 0000000000..c60e5265af --- /dev/null +++ b/tst/Devices/biketestsuite.h @@ -0,0 +1,85 @@ +#pragma once + +#include "gtest/gtest.h" +#include "devices.h" +#include "ErgInterface/erginterface.h" + +#include "Tools/testsettings.h" + +template +class BikeTestSuite : public testing::Test { +private: + bike * device = nullptr; + +protected: + T typeParam; + + uint32_t maxRPM, minRPM; + resistance_t maxResistance, minResistance; + + erginterface * ergInterface = nullptr; + + /** + * @brief Manages the QSettings used during the tests, separate from QSettings stored in the system generally. + */ + TestSettings testSettings; +public: + BikeTestSuite(); + + // Sets up the test fixture. + void SetUp() override; + + // Tears down the test fixture. + virtual void TearDown() override; + + /** + * @brief Test that power doesn't change below the minimum cadence for a constant resistance. + */ + void test_powerFunctions_minCadence(); + + /** + * @brief Test that power doesn't change below the minimum resistance for a constant cadence. + */ + void test_powerFunctions_minResistance(); + + /** + * @brief Test that power doesn't change below the maximum resistance for a constant cadence. + */ + void test_powerFunctions_maxResistance(); + + /** + * @brief Test that power doesn't change above the maximum cadence for a constant resistance. + */ + void test_powerFunctions_maxCadence(); + + /** + * @brief Test that the resistance from power function returns the minimum resistance required to get the same power + * from the power-from-resistance function at the same cadence. + */ + void test_powerFunctions_resistancePowerConversion(); + +}; + + +TYPED_TEST_SUITE(BikeTestSuite, BikeTestDataTypes); + +TYPED_TEST(BikeTestSuite, TestPowerFunctionsMinCadence) { + this->test_powerFunctions_minCadence(); +} + +TYPED_TEST(BikeTestSuite, TestPowerFunctionsMaxCadence) { + this->test_powerFunctions_maxCadence(); +} + +TYPED_TEST(BikeTestSuite, TestPowerFunctionsMinResistance) { + this->test_powerFunctions_minResistance(); +} + +TYPED_TEST(BikeTestSuite, TestPowerFunctionsMaxResistance) { + this->test_powerFunctions_maxResistance(); +} + +TYPED_TEST(BikeTestSuite, TestPowerFunctionsResistancePowerConversion) { + this->test_powerFunctions_resistancePowerConversion(); +} + diff --git a/tst/Devices/devices.h b/tst/Devices/devices.h index a63e73ad4f..2836c38b10 100644 --- a/tst/Devices/devices.h +++ b/tst/Devices/devices.h @@ -1,11 +1,9 @@ -#ifndef DEVICES_H -#define DEVICES_H +#pragma once #include #include #include "gtest/gtest.h" -#include "bluetoothdevicetestdata.h" #include "ActivioTreadmill/activiotreadmilltestdata.h" #include "ApexBike/apexbiketestdata.h" #include "BkoolBike/bkoolbiketestdata.h" @@ -199,7 +197,58 @@ ZiproTreadmillTestData, iConceptBikeTestData, iConceptEllipticalTestData>; -#endif +using BikeTestDataTypes = ::testing::Types< +ApexBikeTestData, +BkoolBikeTestData, +CompuTrainerTestData, +CSCBike1TestData, +CSCBike2TestData, +ChronobikeTestData, +DomyosBikeTestData, +EchelonConnectSportBikeTestData, +FTMSBike1TestData, +FTMSBike2TestData, +FTMSBike3TestData, +FakeBikeTestData, +FitPlusBikeFSTestData, +FitPlusBikeMRKTestData, +FlywheelBike1TestData, +FlywheelBike2TestData, +HorizonGR7BikeTestData, +InspireBikeTestData, +KeepBikeTestData, +M3IBikeTestData, +MCFBikeTestData, +MepanelBikeTestData, +NPECableBike1TestData, +NPECableBike2TestData, +NautilusBikeTestData, +PafersBikeTestData, +ProFormBikeTestData, +ProFormWiFiBikeTestData, +RenphoBike1TestData, +RenphoBike2TestData, +Schwinn170BikeTestData, +SchwinnIC4BikeTestData, +SkandikaWiryBikeTestData, +SnodeBike1TestData, +SnodeBike2TestData, +SoleBikeTestData, +SportsPlusBikeTestData, +SportsTechBikeTestData, +StagesBike1TestData, +StagesBike2TestData, +TacxNeo2TestData, +TrxAppGateUSBBike1TestData, +TrxAppGateUSBBike2TestData, +UltrasportBikeTestData, +WahooKickrSnapBikeTestData, +YesoulBikeTestData, +iConceptBikeTestData>; + + + + diff --git a/tst/Devices/iConceptBike/iconceptbiketestdata.h b/tst/Devices/iConceptBike/iconceptbiketestdata.h index 164c5d56f5..1dc2199ba6 100644 --- a/tst/Devices/iConceptBike/iconceptbiketestdata.h +++ b/tst/Devices/iConceptBike/iconceptbiketestdata.h @@ -5,7 +5,12 @@ class iConceptBikeTestData : public BikeTestData { -void configureSettings(const DeviceDiscoveryInfo &info, bool enable, +protected: + bike* doCreateInstance(const BikeOptions& options) override { + return new iconceptbike(); + } + + void configureSettings(const DeviceDiscoveryInfo &info, bool enable, std::vector &configurations) const override { DeviceDiscoveryInfo config(info); diff --git a/tst/ErgInterface/bikeergfunctions.cpp b/tst/ErgInterface/bikeergfunctions.cpp new file mode 100644 index 0000000000..eeef02cfb6 --- /dev/null +++ b/tst/ErgInterface/bikeergfunctions.cpp @@ -0,0 +1,30 @@ +#include "bikeergfunctions.h" + +void bikeergfunctions::setCadence(int32_t cadence) { this->device->cadenceSensor(cadence); } + +bikeergfunctions::bikeergfunctions(bike *device) : device(device) {} + +std::optional bikeergfunctions::getMaxCadence() const { return std::optional{};} + +std::optional bikeergfunctions::getMinCadence() const { return 0; } + +std::optional bikeergfunctions::getMaxResistance() const { return this->device->maxResistance(); } + +std::optional bikeergfunctions::getMinResistance() const { return 0; } + +double bikeergfunctions::getPower(const int32_t cadence, resistance_t resistance) { + auto originalCadence = this->device->currentCadence().value(); + + this->setCadence(cadence); + auto result = this->device->powerFromResistanceRequest(resistance); + this->setCadence(originalCadence); + return result; +} + +int32_t bikeergfunctions::getResistance(const int32_t cadence, const double power) { + auto originalCadence = this->device->currentCadence().value(); + this->setCadence(cadence); + auto result = this->device->resistanceFromPowerRequest(power); + this->setCadence(originalCadence); + return result; +} diff --git a/tst/ErgInterface/bikeergfunctions.h b/tst/ErgInterface/bikeergfunctions.h new file mode 100644 index 0000000000..de31f68346 --- /dev/null +++ b/tst/ErgInterface/bikeergfunctions.h @@ -0,0 +1,29 @@ +#pragma once + +#include "erginterface.h" +#include "bike.h" + +class bikeergfunctions : public virtual erginterface { + protected: + bike* device; + + void setCadence(int32_t cadence); +public: + bikeergfunctions(bike *device); + + + std::optional getMaxCadence() const override; + + std::optional getMinCadence() const override; + + std::optional getMaxResistance() const override; + + std::optional getMinResistance() const override; + + + double getPower(const int32_t cadence, const resistance_t resistance) override; + + + int32_t getResistance(const int32_t cadence, const double power) override; + +}; diff --git a/tst/ErgInterface/erginterface.h b/tst/ErgInterface/erginterface.h new file mode 100644 index 0000000000..a60fd9e348 --- /dev/null +++ b/tst/ErgInterface/erginterface.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include "definitions.h" + +/** + * @brief An interface for power calculation functions + */ +class erginterface { + protected: + erginterface() {} + erginterface(const erginterface&) {} + public: + /** + * @brief The maximum cadence the object understands. + * @return + */ + virtual std::optional getMaxCadence() const = 0; + + /** + * @brief The minimum cadence the object understands. + * @return + */ + virtual std::optional getMinCadence() const = 0; + + /** + * @brief The maximum resistance the device accepts. + * @return + */ + virtual std::optional getMaxResistance() const = 0; + + /** + * @brief The minimum resistance level. + * @return + */ + virtual std::optional getMinResistance() const = 0; + + + /** + * @brief Gets the power in watts for the given cadence and resistance level. + * @param cadence The cadence in a unit appropriate for the device, e.g. revolutions/strides/strokes per minute. + * @param resistance The resistance level. + * @return + */ + virtual double getPower(const int32_t cadence, const resistance_t resistance) = 0; + + + /** + * @brief Gets the resistance required to acheive the specified power in watts at the specified cadence. + * @param cadence The cadence in a unit appropriate for the device, e.g. revolutions/strides/strokes per minute. + * @param power The power in watts to acheive. + * @return + */ + virtual int32_t getResistance(const int32_t cadence, const double power) = 0; + + /** + * @brief Destructor + */ + virtual ~erginterface() = default; +}; diff --git a/tst/main.cpp b/tst/main.cpp index 372fee8a40..a5e8073363 100644 --- a/tst/main.cpp +++ b/tst/main.cpp @@ -1,8 +1,19 @@ - #include +#include +#include + +// https://forum.qt.io/topic/84229/is-there-a-canonical-way-to-set-up-qapplication-and-google-test-together/2 int main(int argc, char *argv[]) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + QCoreApplication app{argc, argv}; + + QTimer::singleShot(0, [&]() + { + ::testing::InitGoogleTest(&argc, argv); + auto testResult = RUN_ALL_TESTS(); + app.exit(testResult); + }); + + return app.exec(); } diff --git a/tst/qdomyos-zwift-tests.pro b/tst/qdomyos-zwift-tests.pro index 7faaa2e744..84c8f48398 100644 --- a/tst/qdomyos-zwift-tests.pro +++ b/tst/qdomyos-zwift-tests.pro @@ -5,7 +5,7 @@ include(gtest_dependency.pri) TEMPLATE = app -CONFIG += console c++11 +CONFIG += console c++17 CONFIG -= app_bundle CONFIG += thread CONFIG += androidextras @@ -19,10 +19,12 @@ SOURCES += \ Devices/SnodeBike/snodebiketestdata.cpp \ Devices/StagesBike/stagesbiketestdata.cpp \ Devices/TrxAppGateUSBTreadmill/trxappgateusbtreadmilltestdata.cpp \ + Devices/biketestsuite.cpp \ Devices/bluetoothdevicetestdata.cpp \ Devices/bluetoothdevicetestsuite.cpp \ Devices/bluetoothsignalreceiver.cpp \ Devices/devicediscoveryinfo.cpp \ + ErgInterface/bikeergfunctions.cpp \ ToolTests/testsettingstestsuite.cpp \ Tools/testsettings.cpp \ main.cpp @@ -130,6 +132,7 @@ HEADERS += \ Devices/WahooKickrSnapBike/wahookickrsnapbiketestdata.h \ Devices/YesoulBike/yesoulbiketestdata.h \ Devices/ZiproTreadmill/ziprotreadmilltestdata.h \ + Devices/biketestsuite.h \ Devices/bluetoothdevicetestdata.h \ Devices/bluetoothdevicetestsuite.h \ Devices/bluetoothsignalreceiver.h \ @@ -139,5 +142,7 @@ HEADERS += \ Devices/iConceptElliptical/iconceptellipticaltestdata.h \ Devices/YpooElliptical/ypooellipticaltestdata.h \ Devices/TrxAppGateUsbElliptical/trxappgateusbellipticaltestdata.h \ + ErgInterface/bikeergfunctions.h \ + ErgInterface/erginterface.h \ ToolTests/testsettingstestsuite.h \ Tools/testsettings.h