Commit a90248d34c5ffdc2c1272b9207389e16c22b9b8e
Committed by
Moritz Wirger
1 parent
bcac6298
Add tests for BaseDevice, Sensor and SensorList.
Fix some errors in these classes. Make sensor constructors explicit.
Showing
11 changed files
with
550 additions
and
55 deletions
include/hueplusplus/CLIPSensors.h
| @@ -45,14 +45,15 @@ public: | @@ -45,14 +45,15 @@ public: | ||
| 45 | void setURL(const std::string& url); | 45 | void setURL(const std::string& url); |
| 46 | 46 | ||
| 47 | time::AbsoluteTime getLastUpdated() const; | 47 | time::AbsoluteTime getLastUpdated() const; |
| 48 | + | ||
| 48 | protected: | 49 | protected: |
| 49 | - BaseCLIP(Sensor sensor) : BaseDevice(std::move(sensor)) { } | 50 | + explicit BaseCLIP(Sensor sensor) : BaseDevice(std::move(sensor)) { } |
| 50 | }; | 51 | }; |
| 51 | 52 | ||
| 52 | class CLIPSwitch : public BaseCLIP | 53 | class CLIPSwitch : public BaseCLIP |
| 53 | { | 54 | { |
| 54 | public: | 55 | public: |
| 55 | - CLIPSwitch(Sensor sensor) : BaseCLIP(std::move(sensor)) { } | 56 | + explicit CLIPSwitch(Sensor sensor) : BaseCLIP(std::move(sensor)) { } |
| 56 | 57 | ||
| 57 | int getButtonEvent() const; | 58 | int getButtonEvent() const; |
| 58 | void setButtonEvent(int code); | 59 | void setButtonEvent(int code); |
| @@ -62,7 +63,7 @@ public: | @@ -62,7 +63,7 @@ public: | ||
| 62 | class CLIPOpenClose : public BaseCLIP | 63 | class CLIPOpenClose : public BaseCLIP |
| 63 | { | 64 | { |
| 64 | public: | 65 | public: |
| 65 | - CLIPOpenClose(Sensor sensor) : BaseCLIP(std::move(sensor)) { } | 66 | + explicit CLIPOpenClose(Sensor sensor) : BaseCLIP(std::move(sensor)) { } |
| 66 | 67 | ||
| 67 | bool isOpen() const; | 68 | bool isOpen() const; |
| 68 | void setOpen(bool open); | 69 | void setOpen(bool open); |
| @@ -73,7 +74,7 @@ public: | @@ -73,7 +74,7 @@ public: | ||
| 73 | class CLIPPresence : public BaseCLIP | 74 | class CLIPPresence : public BaseCLIP |
| 74 | { | 75 | { |
| 75 | public: | 76 | public: |
| 76 | - CLIPPresence(Sensor sensor) : BaseCLIP(std::move(sensor)) { } | 77 | + explicit CLIPPresence(Sensor sensor) : BaseCLIP(std::move(sensor)) { } |
| 77 | 78 | ||
| 78 | bool getPresence() const; | 79 | bool getPresence() const; |
| 79 | void setPresence(bool presence); | 80 | void setPresence(bool presence); |
| @@ -84,7 +85,7 @@ public: | @@ -84,7 +85,7 @@ public: | ||
| 84 | class CLIPTemperature : public BaseCLIP | 85 | class CLIPTemperature : public BaseCLIP |
| 85 | { | 86 | { |
| 86 | public: | 87 | public: |
| 87 | - CLIPTemperature(Sensor sensor) : BaseCLIP(std::move(sensor)) { } | 88 | + explicit CLIPTemperature(Sensor sensor) : BaseCLIP(std::move(sensor)) { } |
| 88 | 89 | ||
| 89 | int getTemperature() const; | 90 | int getTemperature() const; |
| 90 | void setTemperature(int temperature); | 91 | void setTemperature(int temperature); |
| @@ -94,7 +95,7 @@ public: | @@ -94,7 +95,7 @@ public: | ||
| 94 | class CLIPHumidity : public BaseCLIP | 95 | class CLIPHumidity : public BaseCLIP |
| 95 | { | 96 | { |
| 96 | public: | 97 | public: |
| 97 | - CLIPHumidity(Sensor sensor) : BaseCLIP(std::move(sensor)) { } | 98 | + explicit CLIPHumidity(Sensor sensor) : BaseCLIP(std::move(sensor)) { } |
| 98 | 99 | ||
| 99 | int getHumidity() const; | 100 | int getHumidity() const; |
| 100 | void setHumidity(int humidity); | 101 | void setHumidity(int humidity); |
| @@ -104,7 +105,7 @@ public: | @@ -104,7 +105,7 @@ public: | ||
| 104 | class CLIPLightLevel : public BaseCLIP | 105 | class CLIPLightLevel : public BaseCLIP |
| 105 | { | 106 | { |
| 106 | public: | 107 | public: |
| 107 | - CLIPLightLevel(Sensor sensor) : BaseCLIP(std::move(sensor)) { } | 108 | + explicit CLIPLightLevel(Sensor sensor) : BaseCLIP(std::move(sensor)) { } |
| 108 | 109 | ||
| 109 | int getDarkThreshold() const; | 110 | int getDarkThreshold() const; |
| 110 | void setDarkThreshold(int threshold); | 111 | void setDarkThreshold(int threshold); |
| @@ -122,7 +123,7 @@ public: | @@ -122,7 +123,7 @@ public: | ||
| 122 | class CLIPGenericFlag : public BaseCLIP | 123 | class CLIPGenericFlag : public BaseCLIP |
| 123 | { | 124 | { |
| 124 | public: | 125 | public: |
| 125 | - CLIPGenericFlag(Sensor sensor) : BaseCLIP(std::move(sensor)) { } | 126 | + explicit CLIPGenericFlag(Sensor sensor) : BaseCLIP(std::move(sensor)) { } |
| 126 | 127 | ||
| 127 | bool getFlag() const; | 128 | bool getFlag() const; |
| 128 | void setFlag(bool flag); | 129 | void setFlag(bool flag); |
| @@ -132,7 +133,7 @@ public: | @@ -132,7 +133,7 @@ public: | ||
| 132 | class CLIPGenericStatus : public BaseCLIP | 133 | class CLIPGenericStatus : public BaseCLIP |
| 133 | { | 134 | { |
| 134 | public: | 135 | public: |
| 135 | - CLIPGenericStatus(Sensor sensor) : BaseCLIP(std::move(sensor)) { } | 136 | + explicit CLIPGenericStatus(Sensor sensor) : BaseCLIP(std::move(sensor)) { } |
| 136 | 137 | ||
| 137 | int getStatus() const; | 138 | int getStatus() const; |
| 138 | void setStatus(int status); | 139 | void setStatus(int status); |
include/hueplusplus/Sensor.h
| @@ -2,6 +2,7 @@ | @@ -2,6 +2,7 @@ | ||
| 2 | \file Sensor.h | 2 | \file Sensor.h |
| 3 | Copyright Notice\n | 3 | Copyright Notice\n |
| 4 | Copyright (C) 2020 Stefan Herbrechtsmeier - developer\n | 4 | Copyright (C) 2020 Stefan Herbrechtsmeier - developer\n |
| 5 | + Copyright (C) 2020 Jan Rogall - developer\n | ||
| 5 | 6 | ||
| 6 | This file is part of hueplusplus. | 7 | This file is part of hueplusplus. |
| 7 | 8 | ||
| @@ -45,13 +46,15 @@ Alert alertFromString(const std::string& s); | @@ -45,13 +46,15 @@ Alert alertFromString(const std::string& s); | ||
| 45 | //! | 46 | //! |
| 46 | class Sensor : public BaseDevice | 47 | class Sensor : public BaseDevice |
| 47 | { | 48 | { |
| 48 | - friend class Bridge; | ||
| 49 | - | ||
| 50 | public: | 49 | public: |
| 51 | - //! \brief std dtor | ||
| 52 | - ~Sensor() = default; | 50 | + //! \brief Construct Sensor. |
| 51 | + //! \param id Integer that specifies the id of this sensor | ||
| 52 | + //! \param commands HueCommandAPI for communication with the bridge | ||
| 53 | + //! \param refreshDuration Time between refreshing the cached state. | ||
| 54 | + Sensor(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration); | ||
| 53 | 55 | ||
| 54 | - bool hasSwupdate() const; | 56 | + //!\name Config attributes |
| 57 | + ///@{ | ||
| 55 | 58 | ||
| 56 | bool hasOn() const; | 59 | bool hasOn() const; |
| 57 | // Check whether sensor is on. Does not update when off | 60 | // Check whether sensor is on. Does not update when off |
| @@ -70,34 +73,36 @@ public: | @@ -70,34 +73,36 @@ public: | ||
| 70 | bool hasReachable() const; | 73 | bool hasReachable() const; |
| 71 | bool isReachable() const; | 74 | bool isReachable() const; |
| 72 | 75 | ||
| 73 | - time::AbsoluteTime getLastUpdated() const; | ||
| 74 | - | ||
| 75 | bool hasUserTest() const; | 76 | bool hasUserTest() const; |
| 76 | void setUserTest(bool enabled); | 77 | void setUserTest(bool enabled); |
| 77 | 78 | ||
| 78 | bool hasURL() const; | 79 | bool hasURL() const; |
| 79 | std::string getURL() const; | 80 | std::string getURL() const; |
| 80 | void setURL(const std::string& url); | 81 | void setURL(const std::string& url); |
| 81 | - | 82 | + |
| 82 | std::vector<std::string> getPendingConfig() const; | 83 | std::vector<std::string> getPendingConfig() const; |
| 83 | - | 84 | + |
| 84 | bool hasLEDIndication() const; | 85 | bool hasLEDIndication() const; |
| 85 | bool getLEDIndication() const; | 86 | bool getLEDIndication() const; |
| 86 | void setLEDIndication(bool on); | 87 | void setLEDIndication(bool on); |
| 87 | 88 | ||
| 88 | - nlohmann::json getState() const; | ||
| 89 | - void setStateAttribute(const std::string& key, const nlohmann::json& value); | ||
| 90 | - | ||
| 91 | nlohmann::json getConfig() const; | 89 | nlohmann::json getConfig() const; |
| 92 | void setConfigAttribute(const std::string& key, const nlohmann::json& value); | 90 | void setConfigAttribute(const std::string& key, const nlohmann::json& value); |
| 93 | 91 | ||
| 92 | + ///@} | ||
| 93 | + | ||
| 94 | + time::AbsoluteTime getLastUpdated() const; | ||
| 95 | + | ||
| 96 | + nlohmann::json getState() const; | ||
| 97 | + void setStateAttribute(const std::string& key, const nlohmann::json& value); | ||
| 98 | + | ||
| 94 | bool isCertified() const; | 99 | bool isCertified() const; |
| 95 | bool isPrimary() const; | 100 | bool isPrimary() const; |
| 96 | 101 | ||
| 97 | template <typename T> | 102 | template <typename T> |
| 98 | T asSensorType() const & | 103 | T asSensorType() const & |
| 99 | { | 104 | { |
| 100 | - if (getType() != T::type_str) | 105 | + if (getType() != T::typeStr) |
| 101 | { | 106 | { |
| 102 | throw HueException(FileInfo {__FILE__, __LINE__, __func__}, "Sensor type does not match: " + getType()); | 107 | throw HueException(FileInfo {__FILE__, __LINE__, __func__}, "Sensor type does not match: " + getType()); |
| 103 | } | 108 | } |
| @@ -112,14 +117,6 @@ public: | @@ -112,14 +117,6 @@ public: | ||
| 112 | } | 117 | } |
| 113 | return T(std::move(*this)); | 118 | return T(std::move(*this)); |
| 114 | } | 119 | } |
| 115 | - | ||
| 116 | -protected: | ||
| 117 | - //! \brief Protected ctor that is used by \ref Bridge class. | ||
| 118 | - //! | ||
| 119 | - //! \param id Integer that specifies the id of this sensor | ||
| 120 | - //! \param commands HueCommandAPI for communication with the bridge | ||
| 121 | - //! \param refreshDuration Time between refreshing the cached state. | ||
| 122 | - Sensor(int id, const HueCommandAPI& commands, std::chrono::steady_clock::duration refreshDuration); | ||
| 123 | }; | 120 | }; |
| 124 | 121 | ||
| 125 | class CreateSensor | 122 | class CreateSensor |
| @@ -142,7 +139,7 @@ namespace sensors | @@ -142,7 +139,7 @@ namespace sensors | ||
| 142 | class DaylightSensor : public BaseDevice | 139 | class DaylightSensor : public BaseDevice |
| 143 | { | 140 | { |
| 144 | public: | 141 | public: |
| 145 | - DaylightSensor(Sensor sensor) : BaseDevice(std::move(sensor)) { } | 142 | + explicit DaylightSensor(Sensor sensor) : BaseDevice(std::move(sensor)) { } |
| 146 | 143 | ||
| 147 | bool isOn() const; | 144 | bool isOn() const; |
| 148 | void setOn(bool on); | 145 | void setOn(bool on); |
include/hueplusplus/SensorList.h
| @@ -40,12 +40,15 @@ public: | @@ -40,12 +40,15 @@ public: | ||
| 40 | template <typename T> | 40 | template <typename T> |
| 41 | std::vector<T> getAllByType() | 41 | std::vector<T> getAllByType() |
| 42 | { | 42 | { |
| 43 | + nlohmann::json state = this->stateCache.getValue(); | ||
| 43 | std::vector<T> result; | 44 | std::vector<T> result; |
| 44 | - std::string type = T::typeStr; | ||
| 45 | - // TODO: Maybe only parse the sensors with correct type | ||
| 46 | - for (Sensor& s : getAll()) | 45 | + for (auto it = state.begin(); it != state.end(); ++it) |
| 47 | { | 46 | { |
| 48 | - result.push_back(s.asSensorType<T>()); | 47 | + // Only parse the sensors with the correct type |
| 48 | + if (it->value("type", "") == T::typeStr) | ||
| 49 | + { | ||
| 50 | + result.push_back(get(maybeStoi(it.key())).asSensorType<T>()); | ||
| 51 | + } | ||
| 49 | } | 52 | } |
| 50 | return result; | 53 | return result; |
| 51 | } | 54 | } |
include/hueplusplus/ZLLSensors.h
| @@ -31,7 +31,7 @@ namespace sensors | @@ -31,7 +31,7 @@ namespace sensors | ||
| 31 | class ZGPSwitch : public BaseDevice | 31 | class ZGPSwitch : public BaseDevice |
| 32 | { | 32 | { |
| 33 | public: | 33 | public: |
| 34 | - ZGPSwitch(Sensor sensor) : BaseDevice(std::move(sensor)) { } | 34 | + explicit ZGPSwitch(Sensor sensor) : BaseDevice(std::move(sensor)) { } |
| 35 | 35 | ||
| 36 | bool isOn() const; | 36 | bool isOn() const; |
| 37 | void setOn(bool on); | 37 | void setOn(bool on); |
| @@ -48,7 +48,7 @@ public: | @@ -48,7 +48,7 @@ public: | ||
| 48 | class ZLLSwitch : public BaseDevice | 48 | class ZLLSwitch : public BaseDevice |
| 49 | { | 49 | { |
| 50 | public: | 50 | public: |
| 51 | - ZLLSwitch(Sensor sensor) : BaseDevice(std::move(sensor)) { } | 51 | + explicit ZLLSwitch(Sensor sensor) : BaseDevice(std::move(sensor)) { } |
| 52 | 52 | ||
| 53 | bool isOn() const; | 53 | bool isOn() const; |
| 54 | void setOn(bool on); | 54 | void setOn(bool on); |
| @@ -87,7 +87,7 @@ public: | @@ -87,7 +87,7 @@ public: | ||
| 87 | class ZLLPresence : public BaseDevice | 87 | class ZLLPresence : public BaseDevice |
| 88 | { | 88 | { |
| 89 | public: | 89 | public: |
| 90 | - ZLLPresence(Sensor sensor) : BaseDevice(std::move(sensor)) { } | 90 | + explicit ZLLPresence(Sensor sensor) : BaseDevice(std::move(sensor)) { } |
| 91 | bool isOn() const; | 91 | bool isOn() const; |
| 92 | void setOn(bool on); | 92 | void setOn(bool on); |
| 93 | 93 | ||
| @@ -113,7 +113,7 @@ public: | @@ -113,7 +113,7 @@ public: | ||
| 113 | class ZLLTemperature : public BaseDevice | 113 | class ZLLTemperature : public BaseDevice |
| 114 | { | 114 | { |
| 115 | public: | 115 | public: |
| 116 | - ZLLTemperature(Sensor sensor) : BaseDevice(std::move(sensor)) { } | 116 | + explicit ZLLTemperature(Sensor sensor) : BaseDevice(std::move(sensor)) { } |
| 117 | 117 | ||
| 118 | bool isOn() const; | 118 | bool isOn() const; |
| 119 | void setOn(bool on); | 119 | void setOn(bool on); |
| @@ -133,7 +133,7 @@ public: | @@ -133,7 +133,7 @@ public: | ||
| 133 | class ZLLLightLevel : public BaseDevice | 133 | class ZLLLightLevel : public BaseDevice |
| 134 | { | 134 | { |
| 135 | public: | 135 | public: |
| 136 | - ZLLLightLevel(Sensor sensor) : BaseDevice(std::move(sensor)) { } | 136 | + explicit ZLLLightLevel(Sensor sensor) : BaseDevice(std::move(sensor)) { } |
| 137 | 137 | ||
| 138 | bool isOn() const; | 138 | bool isOn() const; |
| 139 | void setOn(bool on); | 139 | void setOn(bool on); |
src/Bridge.cpp
| @@ -36,6 +36,7 @@ | @@ -36,6 +36,7 @@ | ||
| 36 | #include "hueplusplus/UPnP.h" | 36 | #include "hueplusplus/UPnP.h" |
| 37 | #include "hueplusplus/Utils.h" | 37 | #include "hueplusplus/Utils.h" |
| 38 | 38 | ||
| 39 | + | ||
| 39 | namespace hueplusplus | 40 | namespace hueplusplus |
| 40 | { | 41 | { |
| 41 | BridgeFinder::BridgeFinder(std::shared_ptr<const IHttpHandler> handler) : http_handler(std::move(handler)) { } | 42 | BridgeFinder::BridgeFinder(std::shared_ptr<const IHttpHandler> handler) : http_handler(std::move(handler)) { } |
src/Sensor.cpp
| @@ -57,11 +57,6 @@ Alert alertFromString(const std::string& s) | @@ -57,11 +57,6 @@ Alert alertFromString(const std::string& s) | ||
| 57 | } | 57 | } |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | -bool Sensor::hasSwupdate() const | ||
| 61 | -{ | ||
| 62 | - return state.getValue().at("config").count("swupdate") != 0; | ||
| 63 | -} | ||
| 64 | - | ||
| 65 | bool Sensor::hasOn() const | 60 | bool Sensor::hasOn() const |
| 66 | { | 61 | { |
| 67 | return state.getValue().at("config").count("on") != 0; | 62 | return state.getValue().at("config").count("on") != 0; |
| @@ -124,7 +119,7 @@ void Sensor::sendAlert(Alert type) | @@ -124,7 +119,7 @@ void Sensor::sendAlert(Alert type) | ||
| 124 | alertStr = "none"; | 119 | alertStr = "none"; |
| 125 | break; | 120 | break; |
| 126 | } | 121 | } |
| 127 | - sendPutRequest("/state", nlohmann::json {{"alert", alertStr}}, CURRENT_FILE_INFO); | 122 | + sendPutRequest("/config", nlohmann::json {{"alert", alertStr}}, CURRENT_FILE_INFO); |
| 128 | } | 123 | } |
| 129 | bool Sensor::hasReachable() const | 124 | bool Sensor::hasReachable() const |
| 130 | { | 125 | { |
| @@ -205,7 +200,7 @@ nlohmann::json Sensor::getState() const | @@ -205,7 +200,7 @@ nlohmann::json Sensor::getState() const | ||
| 205 | } | 200 | } |
| 206 | void Sensor::setStateAttribute(const std::string& key, const nlohmann::json& value) | 201 | void Sensor::setStateAttribute(const std::string& key, const nlohmann::json& value) |
| 207 | { | 202 | { |
| 208 | - sendPutRequest("/state", nlohmann::json {{"key", value}}, CURRENT_FILE_INFO); | 203 | + sendPutRequest("/state", nlohmann::json {{key, value}}, CURRENT_FILE_INFO); |
| 209 | } | 204 | } |
| 210 | 205 | ||
| 211 | nlohmann::json Sensor::getConfig() const | 206 | nlohmann::json Sensor::getConfig() const |
| @@ -215,7 +210,7 @@ nlohmann::json Sensor::getConfig() const | @@ -215,7 +210,7 @@ nlohmann::json Sensor::getConfig() const | ||
| 215 | 210 | ||
| 216 | void Sensor::setConfigAttribute(const std::string& key, const nlohmann::json& value) | 211 | void Sensor::setConfigAttribute(const std::string& key, const nlohmann::json& value) |
| 217 | { | 212 | { |
| 218 | - sendPutRequest("/config", nlohmann::json {{"key", value}}, CURRENT_FILE_INFO); | 213 | + sendPutRequest("/config", nlohmann::json {{key, value}}, CURRENT_FILE_INFO); |
| 219 | } | 214 | } |
| 220 | 215 | ||
| 221 | bool Sensor::isCertified() const | 216 | bool Sensor::isCertified() const |
test/CMakeLists.txt
| @@ -31,6 +31,7 @@ target_compile_features(gtest PUBLIC cxx_std_14) | @@ -31,6 +31,7 @@ target_compile_features(gtest PUBLIC cxx_std_14) | ||
| 31 | # define all test sources | 31 | # define all test sources |
| 32 | set(TEST_SOURCES | 32 | set(TEST_SOURCES |
| 33 | test_APICache.cpp | 33 | test_APICache.cpp |
| 34 | + test_BaseDevice.cpp | ||
| 34 | test_BaseHttpHandler.cpp | 35 | test_BaseHttpHandler.cpp |
| 35 | test_Bridge.cpp | 36 | test_Bridge.cpp |
| 36 | test_BridgeConfig.cpp | 37 | test_BridgeConfig.cpp |
| @@ -46,6 +47,8 @@ set(TEST_SOURCES | @@ -46,6 +47,8 @@ set(TEST_SOURCES | ||
| 46 | test_ResourceList.cpp | 47 | test_ResourceList.cpp |
| 47 | test_Scene.cpp | 48 | test_Scene.cpp |
| 48 | test_Schedule.cpp | 49 | test_Schedule.cpp |
| 50 | + test_Sensor.cpp | ||
| 51 | + test_SensorList.cpp | ||
| 49 | test_SimpleBrightnessStrategy.cpp | 52 | test_SimpleBrightnessStrategy.cpp |
| 50 | test_SimpleColorHueStrategy.cpp | 53 | test_SimpleColorHueStrategy.cpp |
| 51 | test_SimpleColorTemperatureStrategy.cpp | 54 | test_SimpleColorTemperatureStrategy.cpp |
test/test_BaseDevice.cpp
0 โ 100644
| 1 | +/** | ||
| 2 | + \file test_BaseDevice.cpp | ||
| 3 | + Copyright Notice\n | ||
| 4 | + Copyright (C) 2020 Jan Rogall - developer\n | ||
| 5 | + | ||
| 6 | + This file is part of hueplusplus. | ||
| 7 | + | ||
| 8 | + hueplusplus is free software: you can redistribute it and/or modify | ||
| 9 | + it under the terms of the GNU Lesser General Public License as published by | ||
| 10 | + the Free Software Foundation, either version 3 of the License, or | ||
| 11 | + (at your option) any later version. | ||
| 12 | + | ||
| 13 | + hueplusplus is distributed in the hope that it will be useful, | ||
| 14 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | + GNU Lesser General Public License for more details. | ||
| 17 | + | ||
| 18 | + You should have received a copy of the GNU Lesser General Public License | ||
| 19 | + along with hueplusplus. If not, see <http://www.gnu.org/licenses/>. | ||
| 20 | +**/ | ||
| 21 | + | ||
| 22 | +#include <gmock/gmock.h> | ||
| 23 | +#include <gtest/gtest.h> | ||
| 24 | + | ||
| 25 | +#include "testhelper.h" | ||
| 26 | + | ||
| 27 | +#include "hueplusplus/BaseDevice.h" | ||
| 28 | +#include "mocks/mock_HttpHandler.h" | ||
| 29 | + | ||
| 30 | +using namespace hueplusplus; | ||
| 31 | +using namespace testing; | ||
| 32 | + | ||
| 33 | +class TestDevice : public BaseDevice | ||
| 34 | +{ | ||
| 35 | +public: | ||
| 36 | + TestDevice(int id, const HueCommandAPI& commands, const std::string& path, | ||
| 37 | + std::chrono::steady_clock::duration refreshDuration) | ||
| 38 | + : BaseDevice(id, commands, path, refreshDuration) | ||
| 39 | + { } | ||
| 40 | +}; | ||
| 41 | + | ||
| 42 | +class BaseDeviceTest : public Test | ||
| 43 | +{ | ||
| 44 | +protected: | ||
| 45 | + std::shared_ptr<MockHttpHandler> handler; | ||
| 46 | + HueCommandAPI commands; | ||
| 47 | + nlohmann::json state; | ||
| 48 | + std::string path = "/test/"; | ||
| 49 | + | ||
| 50 | +protected: | ||
| 51 | + BaseDeviceTest() | ||
| 52 | + : handler(std::make_shared<MockHttpHandler>()), | ||
| 53 | + commands(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler), | ||
| 54 | + state({{"type", "testType"}, {"name", "Test name"}, {"swversion", "1.2.3.4"}, {"modelid", "TEST"}, | ||
| 55 | + {"manufacturername", "testManuf"}, {"uniqueid", "00:00:00:00:00:00:00:00-00"}, | ||
| 56 | + {"productname", "Test type"}}) | ||
| 57 | + { } | ||
| 58 | + | ||
| 59 | + TestDevice getDevice(int id) | ||
| 60 | + { | ||
| 61 | + EXPECT_CALL(*handler, | ||
| 62 | + GETJson("/api/" + getBridgeUsername() + path + std::to_string(id), _, getBridgeIp(), getBridgePort())) | ||
| 63 | + .WillOnce(Return(state)); | ||
| 64 | + return TestDevice(id, commands, path, std::chrono::steady_clock::duration::max()); | ||
| 65 | + } | ||
| 66 | +}; | ||
| 67 | + | ||
| 68 | +TEST_F(BaseDeviceTest, getId) | ||
| 69 | +{ | ||
| 70 | + const int id = 1; | ||
| 71 | + EXPECT_EQ(id, getDevice(id).getId()); | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +TEST_F(BaseDeviceTest, getName) | ||
| 75 | +{ | ||
| 76 | + EXPECT_EQ("Test name", getDevice(1).getName()); | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +TEST_F(BaseDeviceTest, getType) | ||
| 80 | +{ | ||
| 81 | + EXPECT_EQ("testType", getDevice(1).getType()); | ||
| 82 | +} | ||
| 83 | + | ||
| 84 | +TEST_F(BaseDeviceTest, getModelId) | ||
| 85 | +{ | ||
| 86 | + EXPECT_EQ("TEST", getDevice(1).getModelId()); | ||
| 87 | +} | ||
| 88 | + | ||
| 89 | +TEST_F(BaseDeviceTest, getUId) | ||
| 90 | +{ | ||
| 91 | + EXPECT_EQ("00:00:00:00:00:00:00:00-00", getDevice(1).getUId()); | ||
| 92 | + state.erase("uniqueid"); | ||
| 93 | + EXPECT_EQ("", getDevice(1).getUId()); | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +TEST_F(BaseDeviceTest, getManufacturername) | ||
| 97 | +{ | ||
| 98 | + EXPECT_EQ("testManuf", getDevice(1).getManufacturername()); | ||
| 99 | + state.erase("manufacturername"); | ||
| 100 | + EXPECT_EQ("", getDevice(1).getManufacturername()); | ||
| 101 | +} | ||
| 102 | + | ||
| 103 | +TEST_F(BaseDeviceTest, getProductname) | ||
| 104 | +{ | ||
| 105 | + EXPECT_EQ("Test type", getDevice(1).getProductname()); | ||
| 106 | + state.erase("productname"); | ||
| 107 | + EXPECT_EQ("", getDevice(1).getProductname()); | ||
| 108 | +} | ||
| 109 | + | ||
| 110 | +TEST_F(BaseDeviceTest, getSwVersion) | ||
| 111 | +{ | ||
| 112 | + EXPECT_EQ("1.2.3.4", getDevice(1).getSwVersion()); | ||
| 113 | +} | ||
| 114 | + | ||
| 115 | +TEST_F(BaseDeviceTest, setName) | ||
| 116 | +{ | ||
| 117 | + const std::string name = "asdbsdakfl"; | ||
| 118 | + const nlohmann::json request = {{"name", name}}; | ||
| 119 | + const nlohmann::json response = { {{"success", {{"/lights/1/name", name}}}} }; | ||
| 120 | + | ||
| 121 | + TestDevice device = getDevice(1); | ||
| 122 | + EXPECT_CALL(*handler, PUTJson("/api/" + getBridgeUsername() + path + "1/name", request, getBridgeIp(), getBridgePort())) | ||
| 123 | + .WillOnce(Return(response)); | ||
| 124 | + EXPECT_TRUE(device.setName(name)); | ||
| 125 | +} | ||
| 0 | \ No newline at end of file | 126 | \ No newline at end of file |
test/test_Bridge.cpp
| @@ -35,13 +35,13 @@ | @@ -35,13 +35,13 @@ | ||
| 35 | 35 | ||
| 36 | using namespace hueplusplus; | 36 | using namespace hueplusplus; |
| 37 | 37 | ||
| 38 | -class HueFinderTest : public ::testing::Test | 38 | +class BridgeFinderTest : public ::testing::Test |
| 39 | { | 39 | { |
| 40 | protected: | 40 | protected: |
| 41 | std::shared_ptr<MockHttpHandler> handler; | 41 | std::shared_ptr<MockHttpHandler> handler; |
| 42 | 42 | ||
| 43 | protected: | 43 | protected: |
| 44 | - HueFinderTest() : handler(std::make_shared<MockHttpHandler>()) | 44 | + BridgeFinderTest() : handler(std::make_shared<MockHttpHandler>()) |
| 45 | { | 45 | { |
| 46 | using namespace ::testing; | 46 | using namespace ::testing; |
| 47 | 47 | ||
| @@ -59,10 +59,10 @@ protected: | @@ -59,10 +59,10 @@ protected: | ||
| 59 | .Times(AtLeast(1)) | 59 | .Times(AtLeast(1)) |
| 60 | .WillRepeatedly(Return(getBridgeXml())); | 60 | .WillRepeatedly(Return(getBridgeXml())); |
| 61 | } | 61 | } |
| 62 | - ~HueFinderTest() {}; | 62 | + ~BridgeFinderTest() {}; |
| 63 | }; | 63 | }; |
| 64 | 64 | ||
| 65 | -TEST_F(HueFinderTest, FindBridges) | 65 | +TEST_F(BridgeFinderTest, FindBridges) |
| 66 | { | 66 | { |
| 67 | BridgeFinder finder(handler); | 67 | BridgeFinder finder(handler); |
| 68 | std::vector<BridgeFinder::BridgeIdentification> bridges = finder.FindBridges(); | 68 | std::vector<BridgeFinder::BridgeIdentification> bridges = finder.FindBridges(); |
| @@ -85,7 +85,7 @@ TEST_F(HueFinderTest, FindBridges) | @@ -85,7 +85,7 @@ TEST_F(HueFinderTest, FindBridges) | ||
| 85 | EXPECT_TRUE(bridges.empty()); | 85 | EXPECT_TRUE(bridges.empty()); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | -TEST_F(HueFinderTest, GetBridge) | 88 | +TEST_F(BridgeFinderTest, GetBridge) |
| 89 | { | 89 | { |
| 90 | using namespace ::testing; | 90 | using namespace ::testing; |
| 91 | nlohmann::json request {{"devicetype", "HuePlusPlus#User"}}; | 91 | nlohmann::json request {{"devicetype", "HuePlusPlus#User"}}; |
| @@ -120,7 +120,7 @@ TEST_F(HueFinderTest, GetBridge) | @@ -120,7 +120,7 @@ TEST_F(HueFinderTest, GetBridge) | ||
| 120 | Mock::VerifyAndClearExpectations(handler.get()); | 120 | Mock::VerifyAndClearExpectations(handler.get()); |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | -TEST_F(HueFinderTest, AddUsername) | 123 | +TEST_F(BridgeFinderTest, AddUsername) |
| 124 | { | 124 | { |
| 125 | BridgeFinder finder(handler); | 125 | BridgeFinder finder(handler); |
| 126 | std::vector<BridgeFinder::BridgeIdentification> bridges = finder.FindBridges(); | 126 | std::vector<BridgeFinder::BridgeIdentification> bridges = finder.FindBridges(); |
| @@ -133,7 +133,7 @@ TEST_F(HueFinderTest, AddUsername) | @@ -133,7 +133,7 @@ TEST_F(HueFinderTest, AddUsername) | ||
| 133 | EXPECT_EQ(test_bridge.getUsername(), getBridgeUsername()) << "Bridge username not matching"; | 133 | EXPECT_EQ(test_bridge.getUsername(), getBridgeUsername()) << "Bridge username not matching"; |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | -TEST_F(HueFinderTest, GetAllUsernames) | 136 | +TEST_F(BridgeFinderTest, GetAllUsernames) |
| 137 | { | 137 | { |
| 138 | BridgeFinder finder(handler); | 138 | BridgeFinder finder(handler); |
| 139 | std::vector<BridgeFinder::BridgeIdentification> bridges = finder.FindBridges(); | 139 | std::vector<BridgeFinder::BridgeIdentification> bridges = finder.FindBridges(); |
test/test_Sensor.cpp
0 โ 100644
| 1 | +/** | ||
| 2 | + \file test_Sensor.cpp | ||
| 3 | + Copyright Notice\n | ||
| 4 | + Copyright (C) 2020 Jan Rogall - developer\n | ||
| 5 | + | ||
| 6 | + This file is part of hueplusplus. | ||
| 7 | + | ||
| 8 | + hueplusplus is free software: you can redistribute it and/or modify | ||
| 9 | + it under the terms of the GNU Lesser General Public License as published by | ||
| 10 | + the Free Software Foundation, either version 3 of the License, or | ||
| 11 | + (at your option) any later version. | ||
| 12 | + | ||
| 13 | + hueplusplus is distributed in the hope that it will be useful, | ||
| 14 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | + GNU Lesser General Public License for more details. | ||
| 17 | + | ||
| 18 | + You should have received a copy of the GNU Lesser General Public License | ||
| 19 | + along with hueplusplus. If not, see <http://www.gnu.org/licenses/>. | ||
| 20 | +**/ | ||
| 21 | + | ||
| 22 | +#include <hueplusplus/Sensor.h> | ||
| 23 | + | ||
| 24 | +#include <gtest/gtest.h> | ||
| 25 | + | ||
| 26 | +#include "testhelper.h" | ||
| 27 | + | ||
| 28 | +#include "mocks/mock_HttpHandler.h" | ||
| 29 | + | ||
| 30 | +using namespace hueplusplus; | ||
| 31 | +using namespace testing; | ||
| 32 | + | ||
| 33 | +class SensorTest : public Test | ||
| 34 | +{ | ||
| 35 | +protected: | ||
| 36 | + std::shared_ptr<MockHttpHandler> handler; | ||
| 37 | + HueCommandAPI commands; | ||
| 38 | + nlohmann::json state; | ||
| 39 | + | ||
| 40 | +protected: | ||
| 41 | + SensorTest() | ||
| 42 | + : handler(std::make_shared<MockHttpHandler>()), | ||
| 43 | + commands(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler), | ||
| 44 | + state({{"type", "testSensor"}, {"name", "Test sensor"}, {"swversion", "1.2.3.4"}, {"modelid", "test"}, | ||
| 45 | + {"manufacturername", "testManuf"}, {"uniqueid", "00:00:00:00:00:00:00:00-00"}, | ||
| 46 | + {"productname", "Test sensor"}, {"config", nlohmann::json::object()}, | ||
| 47 | + {"state", nlohmann::json::object()}}) | ||
| 48 | + { } | ||
| 49 | + | ||
| 50 | + Sensor getSensor(int id = 1) | ||
| 51 | + { | ||
| 52 | + EXPECT_CALL(*handler, | ||
| 53 | + GETJson( | ||
| 54 | + "/api/" + getBridgeUsername() + "/sensors/" + std::to_string(id), _, getBridgeIp(), getBridgePort())) | ||
| 55 | + .WillOnce(Return(state)); | ||
| 56 | + return Sensor(id, commands, std::chrono::steady_clock::duration::max()); | ||
| 57 | + } | ||
| 58 | +}; | ||
| 59 | + | ||
| 60 | +TEST(Alert, alertFromString) | ||
| 61 | +{ | ||
| 62 | + EXPECT_EQ(Alert::none, alertFromString("none")); | ||
| 63 | + EXPECT_EQ(Alert::select, alertFromString("select")); | ||
| 64 | + EXPECT_EQ(Alert::lselect, alertFromString("lselect")); | ||
| 65 | + EXPECT_EQ(Alert::none, alertFromString("anything")); | ||
| 66 | +} | ||
| 67 | + | ||
| 68 | +TEST(Alert, alertToString) | ||
| 69 | +{ | ||
| 70 | + EXPECT_EQ("none", alertToString(Alert::none)); | ||
| 71 | + EXPECT_EQ("select", alertToString(Alert::select)); | ||
| 72 | + EXPECT_EQ("lselect", alertToString(Alert::lselect)); | ||
| 73 | +} | ||
| 74 | + | ||
| 75 | +TEST_F(SensorTest, On) | ||
| 76 | +{ | ||
| 77 | + EXPECT_FALSE(getSensor().hasOn()); | ||
| 78 | + state["config"]["on"] = true; | ||
| 79 | + EXPECT_TRUE(getSensor().hasOn()); | ||
| 80 | + EXPECT_TRUE(getSensor().isOn()); | ||
| 81 | + | ||
| 82 | + EXPECT_CALL(*handler, | ||
| 83 | + PUTJson("/api/" + getBridgeUsername() + "/sensors/1/config", nlohmann::json({{"on", false}}), getBridgeIp(), | ||
| 84 | + getBridgePort())) | ||
| 85 | + .WillOnce(Return(nlohmann::json {{{"success", {{"/sensors/1/config/on", false}}}}})); | ||
| 86 | + getSensor().setOn(false); | ||
| 87 | +} | ||
| 88 | + | ||
| 89 | +TEST_F(SensorTest, BatteryState) | ||
| 90 | +{ | ||
| 91 | + EXPECT_FALSE(getSensor().hasBatteryState()); | ||
| 92 | + state["config"]["battery"] = 90; | ||
| 93 | + EXPECT_TRUE(getSensor().hasBatteryState()); | ||
| 94 | + EXPECT_EQ(90, getSensor().getBatteryState()); | ||
| 95 | + | ||
| 96 | + int percent = 10; | ||
| 97 | + EXPECT_CALL(*handler, | ||
| 98 | + PUTJson("/api/" + getBridgeUsername() + "/sensors/1/config", nlohmann::json({{"battery", percent}}), | ||
| 99 | + getBridgeIp(), getBridgePort())) | ||
| 100 | + .WillOnce(Return(nlohmann::json {{{"success", {{"/sensors/1/config/battery", percent}}}}})); | ||
| 101 | + getSensor().setBatteryState(percent); | ||
| 102 | +} | ||
| 103 | + | ||
| 104 | +TEST_F(SensorTest, Alert) | ||
| 105 | +{ | ||
| 106 | + EXPECT_FALSE(getSensor().hasAlert()); | ||
| 107 | + state["config"]["alert"] = "none"; | ||
| 108 | + EXPECT_TRUE(getSensor().hasAlert()); | ||
| 109 | + EXPECT_EQ(Alert::none, getSensor().getLastAlert()); | ||
| 110 | + | ||
| 111 | + std::string alert = "lselect"; | ||
| 112 | + EXPECT_CALL(*handler, | ||
| 113 | + PUTJson("/api/" + getBridgeUsername() + "/sensors/1/config", nlohmann::json({{"alert", alert}}), getBridgeIp(), | ||
| 114 | + getBridgePort())) | ||
| 115 | + .WillOnce(Return(nlohmann::json {{{"success", {{"/sensors/1/config/alert", alert}}}}})); | ||
| 116 | + getSensor().sendAlert(Alert::lselect); | ||
| 117 | +} | ||
| 118 | + | ||
| 119 | +TEST_F(SensorTest, Reachable) | ||
| 120 | +{ | ||
| 121 | + EXPECT_FALSE(getSensor().hasReachable()); | ||
| 122 | + state["config"]["reachable"] = false; | ||
| 123 | + EXPECT_TRUE(getSensor().hasReachable()); | ||
| 124 | + EXPECT_FALSE(getSensor().isReachable()); | ||
| 125 | +} | ||
| 126 | + | ||
| 127 | +TEST_F(SensorTest, UserTest) | ||
| 128 | +{ | ||
| 129 | + EXPECT_FALSE(getSensor().hasUserTest()); | ||
| 130 | + state["config"]["usertest"] = false; | ||
| 131 | + EXPECT_TRUE(getSensor().hasUserTest()); | ||
| 132 | + | ||
| 133 | + EXPECT_CALL(*handler, | ||
| 134 | + PUTJson("/api/" + getBridgeUsername() + "/sensors/1/config", nlohmann::json({{"usertest", true}}), | ||
| 135 | + getBridgeIp(), getBridgePort())) | ||
| 136 | + .WillOnce(Return(nlohmann::json {{{"success", {{"/sensors/1/config/usertest", true}}}}})); | ||
| 137 | + getSensor().setUserTest(true); | ||
| 138 | +} | ||
| 139 | + | ||
| 140 | +TEST_F(SensorTest, URL) | ||
| 141 | +{ | ||
| 142 | + EXPECT_FALSE(getSensor().hasURL()); | ||
| 143 | + const std::string url = "https://abc"; | ||
| 144 | + state["config"]["url"] = url; | ||
| 145 | + EXPECT_TRUE(getSensor().hasURL()); | ||
| 146 | + EXPECT_EQ(url, getSensor().getURL()); | ||
| 147 | + | ||
| 148 | + std::string newUrl = "https://cde"; | ||
| 149 | + EXPECT_CALL(*handler, | ||
| 150 | + PUTJson("/api/" + getBridgeUsername() + "/sensors/1/config", nlohmann::json({{"url", newUrl}}), getBridgeIp(), | ||
| 151 | + getBridgePort())) | ||
| 152 | + .WillOnce(Return(nlohmann::json {{{"success", {{"/sensors/1/config/url", newUrl}}}}})); | ||
| 153 | + getSensor().setURL(newUrl); | ||
| 154 | +} | ||
| 155 | + | ||
| 156 | +TEST_F(SensorTest, getPendingConfig) | ||
| 157 | +{ | ||
| 158 | + EXPECT_TRUE(getSensor().getPendingConfig().empty()); | ||
| 159 | + state["config"]["pending"] = nullptr; | ||
| 160 | + EXPECT_TRUE(getSensor().getPendingConfig().empty()); | ||
| 161 | + | ||
| 162 | + state["config"]["pending"] = {"abc", "cde", "def"}; | ||
| 163 | + | ||
| 164 | + EXPECT_THAT(getSensor().getPendingConfig(), UnorderedElementsAre("abc", "cde", "def")); | ||
| 165 | +} | ||
| 166 | + | ||
| 167 | +TEST_F(SensorTest, LEDIndication) | ||
| 168 | +{ | ||
| 169 | + EXPECT_FALSE(getSensor().hasLEDIndication()); | ||
| 170 | + state["config"]["ledindication"] = true; | ||
| 171 | + EXPECT_TRUE(getSensor().hasLEDIndication()); | ||
| 172 | + EXPECT_TRUE(getSensor().getLEDIndication()); | ||
| 173 | + | ||
| 174 | + EXPECT_CALL(*handler, | ||
| 175 | + PUTJson("/api/" + getBridgeUsername() + "/sensors/1/config", nlohmann::json({{"ledindication", false}}), | ||
| 176 | + getBridgeIp(), getBridgePort())) | ||
| 177 | + .WillOnce(Return(nlohmann::json {{{"success", {{"/sensors/1/config/ledindication", false}}}}})); | ||
| 178 | + getSensor().setLEDIndication(false); | ||
| 179 | +} | ||
| 180 | + | ||
| 181 | +TEST_F(SensorTest, getConfig) | ||
| 182 | +{ | ||
| 183 | + EXPECT_EQ(state["config"], getSensor().getConfig()); | ||
| 184 | + state["config"]["attribute"] = false; | ||
| 185 | + EXPECT_EQ(state["config"], getSensor().getConfig()); | ||
| 186 | +} | ||
| 187 | + | ||
| 188 | +TEST_F(SensorTest, setConfigAttribute) | ||
| 189 | +{ | ||
| 190 | + const std::string key = "attribute"; | ||
| 191 | + const nlohmann::json value = "some value"; | ||
| 192 | + EXPECT_CALL(*handler, | ||
| 193 | + PUTJson("/api/" + getBridgeUsername() + "/sensors/1/config", nlohmann::json({{key, value}}), getBridgeIp(), | ||
| 194 | + getBridgePort())) | ||
| 195 | + .WillOnce(Return(nlohmann::json {{{"success", {{"/sensors/1/config/" + key, value}}}}})); | ||
| 196 | + getSensor().setConfigAttribute(key, value); | ||
| 197 | +} | ||
| 198 | + | ||
| 199 | +TEST_F(SensorTest, getLastUpdated) | ||
| 200 | +{ | ||
| 201 | + time::AbsoluteTime none = getSensor().getLastUpdated(); | ||
| 202 | + EXPECT_EQ(std::chrono::seconds(0), none.getBaseTime().time_since_epoch()); | ||
| 203 | + | ||
| 204 | + const std::string timestamp = "2020-05-02T12:00:01"; | ||
| 205 | + state["state"]["lastupdated"] = timestamp; | ||
| 206 | + time::AbsoluteTime time = time::AbsoluteTime::parseUTC(timestamp); | ||
| 207 | + EXPECT_EQ(time.getBaseTime(), getSensor().getLastUpdated().getBaseTime()); | ||
| 208 | +} | ||
| 209 | + | ||
| 210 | +TEST_F(SensorTest, getState) | ||
| 211 | +{ | ||
| 212 | + nlohmann::json stateContent = {{"bla", "bla"}}; | ||
| 213 | + state["state"] = stateContent; | ||
| 214 | + EXPECT_EQ(stateContent, getSensor().getState()); | ||
| 215 | +} | ||
| 216 | + | ||
| 217 | +TEST_F(SensorTest, setStateAttribute) | ||
| 218 | +{ | ||
| 219 | + const std::string key = "attribute"; | ||
| 220 | + const nlohmann::json value = "some value"; | ||
| 221 | + EXPECT_CALL(*handler, | ||
| 222 | + PUTJson("/api/" + getBridgeUsername() + "/sensors/1/state", nlohmann::json({{key, value}}), getBridgeIp(), | ||
| 223 | + getBridgePort())) | ||
| 224 | + .WillOnce(Return(nlohmann::json {{{"success", {{"/sensors/1/state/" + key, value}}}}})); | ||
| 225 | + getSensor().setStateAttribute(key, value); | ||
| 226 | +} | ||
| 227 | + | ||
| 228 | +TEST_F(SensorTest, isCertified) | ||
| 229 | +{ | ||
| 230 | + EXPECT_FALSE(getSensor().isCertified()); | ||
| 231 | + state["capabilities"]["certified"] = true; | ||
| 232 | + EXPECT_TRUE(getSensor().isCertified()); | ||
| 233 | +} | ||
| 234 | + | ||
| 235 | +TEST_F(SensorTest, isPrimary) | ||
| 236 | +{ | ||
| 237 | + EXPECT_FALSE(getSensor().isPrimary()); | ||
| 238 | + state["capabilities"]["primary"] = true; | ||
| 239 | + EXPECT_TRUE(getSensor().isPrimary()); | ||
| 240 | +} | ||
| 241 | + | ||
| 242 | +TEST_F(SensorTest, asSensorType) | ||
| 243 | +{ | ||
| 244 | + // Test both rvalue and const access | ||
| 245 | + { | ||
| 246 | + const Sensor s = getSensor(); | ||
| 247 | + EXPECT_THROW(s.asSensorType<sensors::DaylightSensor>(), HueException); | ||
| 248 | + } | ||
| 249 | + EXPECT_THROW(getSensor().asSensorType<sensors::DaylightSensor>(), HueException); | ||
| 250 | + | ||
| 251 | + state["type"] = sensors::DaylightSensor::typeStr; | ||
| 252 | + sensors::DaylightSensor ds = getSensor().asSensorType<sensors::DaylightSensor>(); | ||
| 253 | + EXPECT_EQ(1, ds.getId()); | ||
| 254 | + const Sensor s = getSensor(); | ||
| 255 | + ds = s.asSensorType<sensors::DaylightSensor>(); | ||
| 256 | + EXPECT_EQ(s.getId(), ds.getId()); | ||
| 257 | +} |
test/test_SensorList.cpp
0 โ 100644
| 1 | +/** | ||
| 2 | + \file test_SensorList.cpp | ||
| 3 | + Copyright Notice\n | ||
| 4 | + Copyright (C) 2020 Jan Rogall - developer\n | ||
| 5 | + | ||
| 6 | + This file is part of hueplusplus. | ||
| 7 | + | ||
| 8 | + hueplusplus is free software: you can redistribute it and/or modify | ||
| 9 | + it under the terms of the GNU Lesser General Public License as published by | ||
| 10 | + the Free Software Foundation, either version 3 of the License, or | ||
| 11 | + (at your option) any later version. | ||
| 12 | + | ||
| 13 | + hueplusplus is distributed in the hope that it will be useful, | ||
| 14 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | + GNU Lesser General Public License for more details. | ||
| 17 | + | ||
| 18 | + You should have received a copy of the GNU Lesser General Public License | ||
| 19 | + along with hueplusplus. If not, see <http://www.gnu.org/licenses/>. | ||
| 20 | +**/ | ||
| 21 | + | ||
| 22 | +#include <gtest/gtest.h> | ||
| 23 | + | ||
| 24 | +#include "testhelper.h" | ||
| 25 | + | ||
| 26 | +#include "hueplusplus/SensorList.h" | ||
| 27 | +#include "mocks/mock_HttpHandler.h" | ||
| 28 | + | ||
| 29 | +using namespace hueplusplus; | ||
| 30 | +using namespace testing; | ||
| 31 | + | ||
| 32 | +class BlaSensor | ||
| 33 | +{ | ||
| 34 | +public: | ||
| 35 | + BlaSensor(Sensor s) { } | ||
| 36 | + | ||
| 37 | + static constexpr const char* typeStr = "bla"; | ||
| 38 | +}; | ||
| 39 | + | ||
| 40 | +TEST(SensorList, getAsType) | ||
| 41 | +{ | ||
| 42 | + auto handler = std::make_shared<MockHttpHandler>(); | ||
| 43 | + HueCommandAPI commands(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler); | ||
| 44 | + | ||
| 45 | + SensorList sensors {commands, "/sensors", std::chrono::steady_clock::duration::max()}; | ||
| 46 | + | ||
| 47 | + const int id = 2; | ||
| 48 | + const nlohmann::json response = {{std::to_string(id), {{"type", "Daylight"}}}}; | ||
| 49 | + | ||
| 50 | + EXPECT_CALL(*handler, | ||
| 51 | + GETJson("/api/" + getBridgeUsername() + "/sensors", nlohmann::json::object(), getBridgeIp(), getBridgePort())) | ||
| 52 | + .WillOnce(Return(response)); | ||
| 53 | + EXPECT_CALL(*handler, | ||
| 54 | + GETJson("/api/" + getBridgeUsername() + "/sensors/" + std::to_string(id), nlohmann::json::object(), | ||
| 55 | + getBridgeIp(), getBridgePort())) | ||
| 56 | + .Times(2) | ||
| 57 | + .WillRepeatedly(Return(nlohmann::json {{"type", "Daylight"}})); | ||
| 58 | + | ||
| 59 | + sensors::DaylightSensor daylightSensor = sensors.getAsType<sensors::DaylightSensor>(id); | ||
| 60 | + EXPECT_THROW(sensors.getAsType<BlaSensor>(2), HueException); | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +TEST(SensorList, getAllByType) | ||
| 64 | +{ | ||
| 65 | + | ||
| 66 | + auto handler = std::make_shared<MockHttpHandler>(); | ||
| 67 | + HueCommandAPI commands(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler); | ||
| 68 | + | ||
| 69 | + SensorList sensors {commands, "/sensors", std::chrono::steady_clock::duration::max()}; | ||
| 70 | + | ||
| 71 | + // Empty | ||
| 72 | + { | ||
| 73 | + const nlohmann::json response = nlohmann::json::object(); | ||
| 74 | + | ||
| 75 | + EXPECT_CALL(*handler, | ||
| 76 | + GETJson( | ||
| 77 | + "/api/" + getBridgeUsername() + "/sensors", nlohmann::json::object(), getBridgeIp(), getBridgePort())) | ||
| 78 | + .WillOnce(Return(response)); | ||
| 79 | + EXPECT_TRUE(sensors.getAllByType<sensors::DaylightSensor>().empty()); | ||
| 80 | + } | ||
| 81 | + // Not matching | ||
| 82 | + { | ||
| 83 | + const nlohmann::json response = {{"1", {{"type", "stuff"}}}}; | ||
| 84 | + EXPECT_CALL(*handler, | ||
| 85 | + GETJson( | ||
| 86 | + "/api/" + getBridgeUsername() + "/sensors", nlohmann::json::object(), getBridgeIp(), getBridgePort())) | ||
| 87 | + .WillOnce(Return(response)); | ||
| 88 | + sensors.refresh(); | ||
| 89 | + EXPECT_TRUE(sensors.getAllByType<sensors::DaylightSensor>().empty()); | ||
| 90 | + } | ||
| 91 | + // Some matching (daylight maybe not the best example, because there is always exactly one) | ||
| 92 | + { | ||
| 93 | + const nlohmann::json response = {{"1", {{"type", "stuff"}}}, {"2", {{"type", "Daylight"}}}, | ||
| 94 | + {"3", {{"type", "stuff"}}}, {"4", {{"type", "Daylight"}}}}; | ||
| 95 | + EXPECT_CALL(*handler, | ||
| 96 | + GETJson( | ||
| 97 | + "/api/" + getBridgeUsername() + "/sensors", nlohmann::json::object(), getBridgeIp(), getBridgePort())) | ||
| 98 | + .WillOnce(Return(response)); | ||
| 99 | + EXPECT_CALL(*handler, | ||
| 100 | + GETJson( | ||
| 101 | + "/api/" + getBridgeUsername() + "/sensors/2", nlohmann::json::object(), getBridgeIp(), getBridgePort())) | ||
| 102 | + .WillOnce(Return(response["2"])); | ||
| 103 | + EXPECT_CALL(*handler, | ||
| 104 | + GETJson( | ||
| 105 | + "/api/" + getBridgeUsername() + "/sensors/4", nlohmann::json::object(), getBridgeIp(), getBridgePort())) | ||
| 106 | + .WillOnce(Return(response["4"])); | ||
| 107 | + sensors.refresh(); | ||
| 108 | + std::vector<sensors::DaylightSensor> result = sensors.getAllByType<sensors::DaylightSensor>(); | ||
| 109 | + EXPECT_THAT(result, | ||
| 110 | + UnorderedElementsAre(Truly([](const auto& s) { return s.getId() == 2; }), | ||
| 111 | + Truly([](const auto& s) { return s.getId() == 4; }))); | ||
| 112 | + } | ||
| 113 | +} |