Commit 6dfa76334b42becb034fe9c8f8afc68c2f4d427d

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

Add tests for sensor implementations.

Fix some copy paste errors.
src/BaseDevice.cpp
... ... @@ -93,7 +93,7 @@ bool BaseDevice::setName(const std::string& name)
93 93  
94 94 BaseDevice::BaseDevice(
95 95 int id, const HueCommandAPI& commands, const std::string& path, std::chrono::steady_clock::duration refreshDuration)
96   - : id(id), state(path + std::to_string(id), commands, refreshDuration), path(path)
  96 + : id(id), path(path), state(path + std::to_string(id), commands, refreshDuration)
97 97 {
98 98 state.refresh();
99 99 }
... ...
src/CLIPSensors.cpp
... ... @@ -188,12 +188,12 @@ constexpr const char* CLIPGenericStatus::typeStr;
188 188  
189 189 int CLIPGenericStatus::getStatus() const
190 190 {
191   - return state.getValue().at("config").at("status").get<int>();
  191 + return state.getValue().at("state").at("status").get<int>();
192 192 }
193 193  
194 194 void CLIPGenericStatus::setStatus(int status)
195 195 {
196   - sendPutRequest("/config", nlohmann::json {{"status", status}}, CURRENT_FILE_INFO);
  196 + sendPutRequest("/state", nlohmann::json {{"status", status}}, CURRENT_FILE_INFO);
197 197 }
198 198 } // namespace sensors
199 199 } // namespace hueplusplus
200 200 \ No newline at end of file
... ...
src/Sensor.cpp
... ... @@ -270,7 +270,7 @@ bool DaylightSensor::isOn() const
270 270  
271 271 void DaylightSensor::setOn(bool on)
272 272 {
273   - sendPutRequest("/config", {"on", on}, CURRENT_FILE_INFO);
  273 + sendPutRequest("/config", { {"on", on} }, CURRENT_FILE_INFO);
274 274 }
275 275  
276 276 bool DaylightSensor::hasBatteryState() const
... ... @@ -324,7 +324,7 @@ void DaylightSensor::setSunsetOffset(int minutes)
324 324  
325 325 bool DaylightSensor::isDaylight() const
326 326 {
327   - return state.getValue().at("config").at("daylight").get<bool>();
  327 + return state.getValue().at("state").at("daylight").get<bool>();
328 328 }
329 329 } // namespace sensors
330 330 } // namespace hueplusplus
... ...
src/ZLLSensors.cpp
... ... @@ -92,7 +92,7 @@ Alert ZLLSwitch::getLastAlert() const
92 92 }
93 93 void ZLLSwitch::sendAlert(Alert type)
94 94 {
95   - sendPutRequest("/state", nlohmann::json {{"alert", alertToString(type)}}, CURRENT_FILE_INFO);
  95 + sendPutRequest("/config", nlohmann::json {{"alert", alertToString(type)}}, CURRENT_FILE_INFO);
96 96 }
97 97 bool ZLLSwitch::isReachable() const
98 98 {
... ... @@ -141,7 +141,7 @@ Alert ZLLPresence::getLastAlert() const
141 141 }
142 142 void ZLLPresence::sendAlert(Alert type)
143 143 {
144   - sendPutRequest("/state", nlohmann::json {{"alert", alertToString(type)}}, CURRENT_FILE_INFO);
  144 + sendPutRequest("/config", nlohmann::json {{"alert", alertToString(type)}}, CURRENT_FILE_INFO);
145 145 }
146 146 bool ZLLPresence::isReachable() const
147 147 {
... ... @@ -158,7 +158,7 @@ int ZLLPresence::getMaxSensitivity() const
158 158 }
159 159 void ZLLPresence::setSensitivity(int sensitivity)
160 160 {
161   - sendPutRequest("/state", nlohmann::json {{"sensitivity", sensitivity}}, CURRENT_FILE_INFO);
  161 + sendPutRequest("/config", nlohmann::json {{"sensitivity", sensitivity}}, CURRENT_FILE_INFO);
162 162 }
163 163 bool ZLLPresence::getPresence() const
164 164 {
... ... @@ -185,7 +185,7 @@ bool ZLLTemperature::isOn() const
185 185  
186 186 void ZLLTemperature::setOn(bool on)
187 187 {
188   - sendPutRequest("/config", {"on", on}, CURRENT_FILE_INFO);
  188 + sendPutRequest("/config", {{"on", on}}, CURRENT_FILE_INFO);
189 189 }
190 190 bool ZLLTemperature::hasBatteryState() const
191 191 {
... ... @@ -203,7 +203,7 @@ Alert ZLLTemperature::getLastAlert() const
203 203 }
204 204 void ZLLTemperature::sendAlert(Alert type)
205 205 {
206   - sendPutRequest("/state", nlohmann::json {{"alert", alertToString(type)}}, CURRENT_FILE_INFO);
  206 + sendPutRequest("/config", nlohmann::json {{"alert", alertToString(type)}}, CURRENT_FILE_INFO);
207 207 }
208 208 bool ZLLTemperature::isReachable() const
209 209 {
... ... @@ -224,7 +224,7 @@ bool ZLLLightLevel::isOn() const
224 224  
225 225 void ZLLLightLevel::setOn(bool on)
226 226 {
227   - sendPutRequest("/config", {"on", on}, CURRENT_FILE_INFO);
  227 + sendPutRequest("/config", {{"on", on}}, CURRENT_FILE_INFO);
228 228 }
229 229 bool ZLLLightLevel::hasBatteryState() const
230 230 {
... ...
test/CMakeLists.txt
... ... @@ -35,6 +35,7 @@ set(TEST_SOURCES
35 35 test_BaseHttpHandler.cpp
36 36 test_Bridge.cpp
37 37 test_BridgeConfig.cpp
  38 + test_SensorImpls.cpp
38 39 test_ColorUnits.cpp
39 40 test_ExtendedColorHueStrategy.cpp
40 41 test_ExtendedColorTemperatureStrategy.cpp
... ...
test/test_SensorImpls.cpp 0 โ†’ 100644
  1 +/**
  2 + \file test_SensorImpls.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/CLIPSensors.h>
  23 +#include <hueplusplus/ZLLSensors.h>
  24 +
  25 +#include <gtest/gtest.h>
  26 +
  27 +#include "testhelper.h"
  28 +
  29 +#include "mocks/mock_HttpHandler.h"
  30 +
  31 +using namespace testing;
  32 +using namespace hueplusplus;
  33 +using namespace hueplusplus::sensors;
  34 +
  35 +// Many sensor classes contain duplicate methods, with the type parameterized tests at least the test cases
  36 +// do not have to be duplicated
  37 +template <typename T>
  38 +class SensorImplTest : public Test
  39 +{
  40 +protected:
  41 + std::shared_ptr<MockHttpHandler> handler;
  42 + HueCommandAPI commands;
  43 + nlohmann::json state;
  44 +
  45 +protected:
  46 + SensorImplTest()
  47 + : handler(std::make_shared<MockHttpHandler>()),
  48 + commands(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler),
  49 + state({{"type", T::typeStr}, {"config", nlohmann::json::object()}, {"state", nlohmann::json::object()}})
  50 + { }
  51 +
  52 + void expectConfigSet(const std::string& key, const nlohmann::json& value)
  53 + {
  54 + EXPECT_CALL(*handler,
  55 + PUTJson("/api/" + getBridgeUsername() + "/sensors/1/config", nlohmann::json({{key, value}}), getBridgeIp(),
  56 + getBridgePort()))
  57 + .WillOnce(Return(nlohmann::json {{{"success", {{"/sensors/1/config/" + key, value}}}}}));
  58 + }
  59 + void expectStateSet(const std::string& key, const nlohmann::json& value)
  60 + {
  61 + EXPECT_CALL(*handler,
  62 + PUTJson("/api/" + getBridgeUsername() + "/sensors/1/state", nlohmann::json({{key, value}}), getBridgeIp(),
  63 + getBridgePort()))
  64 + .WillOnce(Return(nlohmann::json {{{"success", {{"/sensors/1/state/" + key, value}}}}}));
  65 + }
  66 +
  67 + T getSensor()
  68 + {
  69 + EXPECT_CALL(*handler, GETJson("/api/" + getBridgeUsername() + "/sensors/1", _, getBridgeIp(), getBridgePort()))
  70 + .WillOnce(Return(state));
  71 + return T(Sensor(1, commands, std::chrono::steady_clock::duration::max()));
  72 + }
  73 +};
  74 +
  75 +// Sensors with shared methods
  76 +
  77 +template <typename T>
  78 +class SensorOnTest : public SensorImplTest<T>
  79 +{ };
  80 +// Only need to test one CLIP type, because they share the basic methods
  81 +using SensorOnTypes
  82 + = Types<CLIPSwitch, ZGPSwitch, ZLLSwitch, ZLLPresence, ZLLTemperature, ZLLLightLevel, DaylightSensor>;
  83 +TYPED_TEST_SUITE(SensorOnTest, SensorOnTypes);
  84 +
  85 +template <typename T>
  86 +class SensorBatteryTest : public SensorImplTest<T>
  87 +{ };
  88 +using SensorBatteryTypes = Types<CLIPSwitch, ZLLSwitch, ZLLPresence, ZLLTemperature, ZLLLightLevel, DaylightSensor>;
  89 +TYPED_TEST_SUITE(SensorBatteryTest, SensorBatteryTypes);
  90 +
  91 +template <typename T>
  92 +class SensorReachableTest : public SensorImplTest<T>
  93 +{ };
  94 +using SensorReachableTypes = Types<CLIPSwitch, ZLLSwitch, ZLLPresence, ZLLTemperature, ZLLLightLevel>;
  95 +TYPED_TEST_SUITE(SensorReachableTest, SensorReachableTypes);
  96 +
  97 +template <typename T>
  98 +class SensorUpdateTest : public SensorImplTest<T>
  99 +{ };
  100 +using SensorUpdateTypes = Types<CLIPSwitch, ZLLSwitch, ZLLPresence, ZLLLightLevel>;
  101 +TYPED_TEST_SUITE(SensorUpdateTest, SensorUpdateTypes);
  102 +
  103 +template <typename T>
  104 +class SensorAlertTest : public SensorImplTest<T>
  105 +{ };
  106 +using SensorAlertTypes = Types<ZLLSwitch, ZLLPresence, ZLLTemperature>;
  107 +TYPED_TEST_SUITE(SensorAlertTest, SensorAlertTypes);
  108 +
  109 +template <typename T>
  110 +class SensorButtonTest : public SensorImplTest<T>
  111 +{ };
  112 +using SensorButtonTypes = Types<CLIPSwitch, ZLLSwitch, ZGPSwitch>;
  113 +TYPED_TEST_SUITE(SensorButtonTest, SensorButtonTypes);
  114 +
  115 +template <typename T>
  116 +class SensorTemperatureTest : public SensorImplTest<T>
  117 +{ };
  118 +using SensorTemperatureTypes = Types<CLIPTemperature, ZLLTemperature>;
  119 +TYPED_TEST_SUITE(SensorTemperatureTest, SensorTemperatureTypes);
  120 +
  121 +template <typename T>
  122 +class SensorLightLevelTest : public SensorImplTest<T>
  123 +{ };
  124 +using SensorLightLevelTypes = Types<CLIPLightLevel, ZLLLightLevel>;
  125 +TYPED_TEST_SUITE(SensorLightLevelTest, SensorLightLevelTypes);
  126 +
  127 +template <typename T>
  128 +class SensorPresenceTest : public SensorImplTest<T>
  129 +{ };
  130 +using SensorPresenceTypes = Types<CLIPPresence, ZLLPresence>;
  131 +TYPED_TEST_SUITE(SensorPresenceTest, SensorPresenceTypes);
  132 +
  133 +// Sensors with unique methods
  134 +
  135 +class DaylightSensorTest : public SensorImplTest<DaylightSensor>
  136 +{ };
  137 +
  138 +class ZLLPresenceTest : public SensorImplTest<ZLLPresence>
  139 +{ };
  140 +
  141 +class CLIPSwitchTest : public SensorImplTest<CLIPSwitch>
  142 +{ };
  143 +
  144 +class CLIPOpenCloseTest : public SensorImplTest<CLIPOpenClose>
  145 +{ };
  146 +
  147 +class CLIPPresenceTest : public SensorImplTest<CLIPPresence>
  148 +{ };
  149 +
  150 +class CLIPTemperatureTest : public SensorImplTest<CLIPTemperature>
  151 +{ };
  152 +
  153 +class CLIPHumidityTest : public SensorImplTest<CLIPHumidity>
  154 +{ };
  155 +
  156 +class CLIPGenericFlagTest : public SensorImplTest<CLIPGenericFlag>
  157 +{ };
  158 +
  159 +class CLIPGenericStatusTest : public SensorImplTest<CLIPGenericStatus>
  160 +{ };
  161 +
  162 +TYPED_TEST(SensorOnTest, On)
  163 +{
  164 + this->state["config"]["on"] = false;
  165 + EXPECT_FALSE(this->getSensor().isOn());
  166 + this->state["config"]["on"] = true;
  167 + EXPECT_TRUE(this->getSensor().isOn());
  168 +
  169 + this->expectConfigSet("on", false);
  170 + this->getSensor().setOn(false);
  171 +}
  172 +
  173 +TYPED_TEST(SensorBatteryTest, BatteryState)
  174 +{
  175 + EXPECT_FALSE(this->getSensor().hasBatteryState());
  176 + this->state["config"]["battery"] = 90;
  177 + EXPECT_TRUE(this->getSensor().hasBatteryState());
  178 + EXPECT_EQ(90, this->getSensor().getBatteryState());
  179 +}
  180 +
  181 +TYPED_TEST(SensorReachableTest, Reachable)
  182 +{
  183 + this->state["config"]["reachable"] = true;
  184 + EXPECT_TRUE(this->getSensor().isReachable());
  185 +}
  186 +
  187 +TYPED_TEST(SensorUpdateTest, getLastUpdated)
  188 +{
  189 + time::AbsoluteTime none = this->getSensor().getLastUpdated();
  190 + EXPECT_EQ(std::chrono::seconds(0), none.getBaseTime().time_since_epoch());
  191 +
  192 + const std::string timestamp = "2020-05-02T12:00:01";
  193 + this->state["state"]["lastupdated"] = timestamp;
  194 + time::AbsoluteTime time = time::AbsoluteTime::parseUTC(timestamp);
  195 + EXPECT_EQ(time.getBaseTime(), this->getSensor().getLastUpdated().getBaseTime());
  196 +}
  197 +
  198 +TYPED_TEST(SensorAlertTest, Alert)
  199 +{
  200 + this->state["config"]["alert"] = "none";
  201 + EXPECT_EQ(Alert::none, this->getSensor().getLastAlert());
  202 +
  203 + this->expectConfigSet("alert", "lselect");
  204 + this->getSensor().sendAlert(Alert::lselect);
  205 +}
  206 +
  207 +TYPED_TEST(SensorButtonTest, ButtonEvent)
  208 +{
  209 + int code = 12;
  210 + this->state["state"]["buttonevent"] = code;
  211 + EXPECT_EQ(code, this->getSensor().getButtonEvent());
  212 +}
  213 +
  214 +TYPED_TEST(SensorTemperatureTest, Temperature)
  215 +{
  216 + int temperature = 1200;
  217 + this->state["state"]["temperature"] = temperature;
  218 + EXPECT_EQ(temperature, this->getSensor().getTemperature());
  219 +}
  220 +
  221 +TYPED_TEST(SensorLightLevelTest, LightLevel)
  222 +{
  223 + int lightLevel = 1200;
  224 + this->state["state"] = {{"lightlevel", lightLevel}, {"dark", true}, {"daylight", false}};
  225 + EXPECT_EQ(lightLevel, this->getSensor().getLightLevel());
  226 + EXPECT_TRUE(this->getSensor().isDark());
  227 + EXPECT_FALSE(this->getSensor().isDaylight());
  228 +}
  229 +
  230 +TYPED_TEST(SensorLightLevelTest, DarkThreshold)
  231 +{
  232 + int darkThreshold = 12000;
  233 + this->state["config"]["tholddark"] = darkThreshold;
  234 + EXPECT_EQ(darkThreshold, this->getSensor().getDarkThreshold());
  235 +
  236 + int newThreshold = 10;
  237 + this->expectConfigSet("tholddark", newThreshold);
  238 + this->getSensor().setDarkThreshold(newThreshold);
  239 +}
  240 +
  241 +TYPED_TEST(SensorLightLevelTest, ThresholdOffset)
  242 +{
  243 + int offset = 12000;
  244 + this->state["config"]["tholdoffset"] = offset;
  245 + EXPECT_EQ(offset, this->getSensor().getThresholdOffset());
  246 +
  247 + int newOffset = 10;
  248 + this->expectConfigSet("tholdoffset", newOffset);
  249 + this->getSensor().setThresholdOffset(newOffset);
  250 +}
  251 +
  252 +TYPED_TEST(SensorPresenceTest, Presence)
  253 +{
  254 + this->state["state"]["presence"] = true;
  255 + EXPECT_TRUE(this->getSensor().getPresence());
  256 +}
  257 +
  258 +TEST_F(DaylightSensorTest, Coordinates)
  259 +{
  260 + const std::string lat = "000.0000N";
  261 + const std::string lon = "000.0000E";
  262 + EXPECT_CALL(*handler,
  263 + PUTJson("/api/" + getBridgeUsername() + "/sensors/1/config", nlohmann::json({{"lat", lat}, {"long", lon}}),
  264 + getBridgeIp(), getBridgePort()))
  265 + .WillOnce(Return(nlohmann::json {
  266 + {{"success", {{"/sensors/1/config/lat", lat}}}}, {{"success", {{"/sensors/1/config/long", lon}}}}}));
  267 + getSensor().setCoordinates(lat, lon);
  268 + state["config"]["configured"] = true;
  269 + EXPECT_TRUE(getSensor().isConfigured());
  270 +}
  271 +
  272 +TEST_F(DaylightSensorTest, SunriseOffset)
  273 +{
  274 + int offset = 10;
  275 + state["config"]["sunriseoffset"] = offset;
  276 + EXPECT_EQ(offset, getSensor().getSunriseOffset());
  277 +
  278 + int newOffset = 20;
  279 + expectConfigSet("sunriseoffset", newOffset);
  280 + getSensor().setSunriseOffset(newOffset);
  281 +}
  282 +
  283 +TEST_F(DaylightSensorTest, SunsetOffset)
  284 +{
  285 + int offset = 10;
  286 + state["config"]["sunsetoffset"] = offset;
  287 + EXPECT_EQ(offset, getSensor().getSunsetOffset());
  288 +
  289 + int newOffset = 20;
  290 + expectConfigSet("sunsetoffset", newOffset);
  291 + getSensor().setSunsetOffset(newOffset);
  292 +}
  293 +
  294 +TEST_F(DaylightSensorTest, isDaylight)
  295 +{
  296 + state["state"]["daylight"] = true;
  297 + EXPECT_TRUE(getSensor().isDaylight());
  298 +}
  299 +
  300 +TEST_F(ZLLPresenceTest, Sensitivity)
  301 +{
  302 + int sensitivity = 1000;
  303 + state["config"]["sensitivity"] = sensitivity;
  304 + int maxSensitivity = 10000;
  305 + state["config"]["sensitivitymax"] = maxSensitivity;
  306 + EXPECT_EQ(sensitivity, getSensor().getSensitivity());
  307 + EXPECT_EQ(maxSensitivity, getSensor().getMaxSensitivity());
  308 +
  309 + int newSensitivity = 10;
  310 + expectConfigSet("sensitivity", newSensitivity);
  311 + this->getSensor().setSensitivity(newSensitivity);
  312 +}
  313 +
  314 +TEST_F(CLIPSwitchTest, setBatteryState)
  315 +{
  316 + int percent = 10;
  317 + expectConfigSet("battery", percent);
  318 + this->getSensor().setBatteryState(percent);
  319 +}
  320 +
  321 +TEST_F(CLIPSwitchTest, URL)
  322 +{
  323 + EXPECT_FALSE(getSensor().hasURL());
  324 + const std::string url = "https://abc";
  325 + state["config"]["url"] = url;
  326 + EXPECT_TRUE(getSensor().hasURL());
  327 + EXPECT_EQ(url, getSensor().getURL());
  328 +
  329 + std::string newUrl = "https://cde";
  330 + expectConfigSet("url", newUrl);
  331 + getSensor().setURL(newUrl);
  332 +}
  333 +
  334 +TEST_F(CLIPSwitchTest, setButtonEvent)
  335 +{
  336 + int code = 10;
  337 + expectStateSet("buttonevent", code);
  338 + this->getSensor().setButtonEvent(code);
  339 +}
  340 +
  341 +TEST_F(CLIPOpenCloseTest, Open)
  342 +{
  343 + state["state"]["open"] = true;
  344 + EXPECT_TRUE(getSensor().isOpen());
  345 +
  346 + bool open = false;
  347 + expectStateSet("open", open);
  348 + getSensor().setOpen(open);
  349 +}
  350 +
  351 +TEST_F(CLIPPresenceTest, setPresence)
  352 +{
  353 + bool presence = false;
  354 + expectStateSet("presence", presence);
  355 + getSensor().setPresence(presence);
  356 +}
  357 +
  358 +TEST_F(CLIPTemperatureTest, setPresence)
  359 +{
  360 + int temperature = 1100;
  361 + expectStateSet("temperature", temperature);
  362 + getSensor().setTemperature(temperature);
  363 +}
  364 +
  365 +TEST_F(CLIPHumidityTest, Humidity)
  366 +{
  367 + int humidity = 100;
  368 + state["state"]["humidity"] = humidity;
  369 + EXPECT_EQ(humidity, getSensor().getHumidity());
  370 +
  371 + int newHumidity = 1100;
  372 + expectStateSet("humidity", newHumidity);
  373 + getSensor().setHumidity(newHumidity);
  374 +}
  375 +
  376 +TEST_F(CLIPGenericFlagTest, Flag)
  377 +{
  378 + state["state"]["flag"] = true;
  379 + EXPECT_TRUE(getSensor().getFlag());
  380 + expectStateSet("flag", false);
  381 + getSensor().setFlag(false);
  382 +}
  383 +
  384 +TEST_F(CLIPGenericStatusTest, Status)
  385 +{
  386 + int status = 32;
  387 + state["state"]["status"] = status;
  388 + EXPECT_EQ(status, getSensor().getStatus());
  389 + int newStatus = 52;
  390 + expectStateSet("status", newStatus);
  391 + getSensor().setStatus(newStatus);
  392 +}
... ...