Commit a90248d34c5ffdc2c1272b9207389e16c22b9b8e

Authored by Jojo-1000
Committed by Moritz Wirger
1 parent bcac6298

Add tests for BaseDevice, Sensor and SensorList.

Fix some errors in these classes.
Make sensor constructors explicit.
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&amp; s) @@ -57,11 +57,6 @@ Alert alertFromString(const std::string&amp; 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 +}