Commit 62c09fce49549eb26ea2f867bee9ad827a77f135

Authored by Moritz Wirger
1 parent 3fb907aa

Add first crude test for Hue class and all its prerequisites

hueplusplus/test/mocks/mock_HttpHandler.h 0 → 100755
  1 +/**
  2 + \file mock_HttpHandler.h
  3 + Copyright Notice\n
  4 + Copyright (C) 2017 Jan Rogall - developer\n
  5 + Copyright (C) 2017 Moritz Wirger - developer\n
  6 +
  7 + This program is free software; you can redistribute it and/or modify
  8 + it under the terms of the GNU General Public License as published by
  9 + the Free Software Foundation; either version 3 of the License, or
  10 + (at your option) any later version.
  11 + This program is distributed in the hope that it will be useful,
  12 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + GNU General Public License for more details.
  15 + You should have received a copy of the GNU General Public License
  16 + along with this program; if not, write to the Free Software Foundation,
  17 + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18 +**/
  19 +
  20 +#ifndef _MOCK_HTTPHANDLER_H
  21 +#define _MOCK_HTTPHANDLER_H
  22 +
  23 +#include <string>
  24 +#include <vector>
  25 +
  26 +#include <gmock/gmock.h>
  27 +
  28 +#include "../hueplusplus/include/HttpHandler.h"
  29 +#include "../hueplusplus/include/json/json.h"
  30 +
  31 +//! Mock Class
  32 +class MockHttpHandler : public IHttpHandler
  33 +{
  34 +public:
  35 +
  36 + MOCK_CONST_METHOD3( send, std::string(const std::string &msg, const std::string &adr, int port) );
  37 +
  38 + MOCK_CONST_METHOD3( sendGetHTTPBody, std::string(const std::string &msg, const std::string &adr, int port) );
  39 +
  40 + MOCK_CONST_METHOD4( sendMulticast, std::vector<std::string>(const std::string &msg, const std::string &adr, int port, int timeout) );
  41 +
  42 + MOCK_CONST_METHOD6( sendHTTPRequest, std::string(std::string method, std::string uri, std::string content_type, std::string body, const std::string &adr, int port) );
  43 +
  44 + MOCK_CONST_METHOD5( GETString, std::string(std::string uri, std::string content_type, std::string body, const std::string &adr, int port) );
  45 +
  46 + MOCK_CONST_METHOD5( POSTString, std::string(std::string uri, std::string content_type, std::string body, const std::string &adr, int port) );
  47 +
  48 + MOCK_CONST_METHOD5( PUTString, std::string(std::string uri, std::string content_type, std::string body, const std::string &adr, int port) );
  49 +
  50 + MOCK_CONST_METHOD5( DELETEString, std::string(std::string uri, std::string content_type, std::string body, const std::string &adr, int port) );
  51 +
  52 + MOCK_CONST_METHOD4( GETJson, Json::Value(std::string uri, const Json::Value& body, const std::string &adr, int port) );
  53 +
  54 + MOCK_CONST_METHOD4( POSTJson, Json::Value(std::string uri, const Json::Value& body, const std::string &adr, int port) );
  55 +
  56 + MOCK_CONST_METHOD4( PUTJson, Json::Value(std::string uri, const Json::Value& body, const std::string &adr, int port) );
  57 +
  58 + MOCK_CONST_METHOD4( DELETEJson, Json::Value(std::string uri, const Json::Value& body, const std::string &adr, int port) );
  59 +};
  60 +
  61 +#endif
... ...
hueplusplus/test/test_Hue.cpp 0 → 100755
  1 +#include <gtest/gtest.h>
  2 +#include <gmock/gmock.h>
  3 +
  4 +#include "../include/Hue.h"
  5 +#include "../include/json/json.h"
  6 +#include "mocks/mock_HttpHandler.h"
  7 +#include "testhelper.h"
  8 +
  9 +#include <iostream>
  10 +#include <memory>
  11 +#include <string>
  12 +
  13 +
  14 +class HueFinderTest : public ::testing::Test
  15 +{
  16 +protected:
  17 + std::shared_ptr<MockHttpHandler> handler;
  18 +protected:
  19 + HueFinderTest()
  20 + {
  21 + handler = std::make_shared<MockHttpHandler>();
  22 +
  23 + EXPECT_CALL(*handler, sendMulticast("M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 5\r\nST: ssdp:all\r\n\r\n", "239.255.255.250", 1900, 5))
  24 + .Times(::testing::AtLeast(1))
  25 + .WillRepeatedly(::testing::Return(multicast_reply));
  26 +
  27 + EXPECT_CALL(*handler, GETString("/description.xml", "application/xml", "", "192.168.2.1", 80))
  28 + .Times(0);
  29 +
  30 + EXPECT_CALL(*handler, GETString("/description.xml", "application/xml", "", bridge_ip, 80))
  31 + .Times(::testing::AtLeast(1))
  32 + .WillRepeatedly(::testing::Return(brige_xml));
  33 + }
  34 + ~HueFinderTest(){};
  35 +};
  36 +
  37 +TEST_F(HueFinderTest, FindBridges)
  38 +{
  39 + HueFinder finder(handler);
  40 + std::vector<HueFinder::HueIdentification> bridges = finder.FindBridges();
  41 +
  42 + HueFinder::HueIdentification bridge_to_comp;
  43 + bridge_to_comp.ip = bridge_ip;
  44 + bridge_to_comp.mac = bridge_mac;
  45 +
  46 + EXPECT_EQ(bridges.size(), 1) << "HueFinder found more than one Bridge";
  47 + EXPECT_EQ(bridges[0].ip, bridge_to_comp.ip) << "HueIdentification ip does not match";
  48 + EXPECT_EQ(bridges[0].mac, bridge_to_comp.mac) << "HueIdentification mac does not match";
  49 +}
  50 +
  51 +TEST_F(HueFinderTest, GetBridge)
  52 +{
  53 + Json::Value request;
  54 + request["devicetype"] = "HuePlusPlus#User";
  55 +
  56 + Json::Value user_ret_uns;
  57 + user_ret_uns = Json::Value(Json::arrayValue);
  58 + user_ret_uns[0] = Json::Value(Json::objectValue);
  59 + user_ret_uns[0]["error"] = Json::Value(Json::objectValue);
  60 + user_ret_uns[0]["error"]["type"] = 101;
  61 + user_ret_uns[0]["error"]["address"] = "";
  62 + user_ret_uns[0]["error"]["description"] = "link button not pressed";
  63 +
  64 + EXPECT_CALL(*handler, GETJson("/api", request, bridge_ip, 80))
  65 + .Times(::testing::AtLeast(1))
  66 + .WillRepeatedly(::testing::Return(user_ret_uns));
  67 +
  68 + HueFinder finder(handler);
  69 + std::vector<HueFinder::HueIdentification> bridges = finder.FindBridges();
  70 +
  71 + ASSERT_THROW(finder.GetBridge(bridges[0]), std::runtime_error);
  72 +
  73 + Json::Value user_ret_suc;
  74 + user_ret_suc = Json::Value(Json::arrayValue);
  75 + user_ret_suc[0] = Json::Value(Json::objectValue);
  76 + user_ret_suc[0]["success"] = Json::Value(Json::objectValue);
  77 + user_ret_suc[0]["success"]["username"] = bridge_username;
  78 +
  79 + EXPECT_CALL(*handler, GETJson("/api", request, bridge_ip, 80))
  80 + .Times(1)
  81 + .WillOnce(::testing::Return(user_ret_suc));
  82 +
  83 + finder = HueFinder(handler);
  84 + bridges = finder.FindBridges();
  85 +
  86 + Hue test_bridge = finder.GetBridge(bridges[0]);
  87 +
  88 + EXPECT_EQ(test_bridge.getBridgeIP(), bridge_ip) << "Bridge IP not matching";
  89 + EXPECT_EQ(test_bridge.getUsername(), bridge_username) << "Bridge username not matching";
  90 +
  91 +
  92 +}
  93 +
  94 +TEST_F(HueFinderTest, AddUsername)
  95 +{
  96 + HueFinder finder(handler);
  97 + std::vector<HueFinder::HueIdentification> bridges = finder.FindBridges();
  98 +
  99 + finder.AddUsername(bridges[0].mac, bridge_username);
  100 + Hue test_bridge = finder.GetBridge(bridges[0]);
  101 +
  102 + EXPECT_EQ(test_bridge.getBridgeIP(), bridge_ip) << "Bridge IP not matching";
  103 + EXPECT_EQ(test_bridge.getUsername(), bridge_username) << "Bridge username not matching";
  104 +}
  105 +
  106 +TEST_F(HueFinderTest, GetAllUsernames)
  107 +{
  108 + HueFinder finder(handler);
  109 + std::vector<HueFinder::HueIdentification> bridges = finder.FindBridges();
  110 +
  111 + finder.AddUsername(bridges[0].mac, bridge_username);
  112 +
  113 + std::map<std::string, std::string> users = finder.GetAllUsernames();
  114 + EXPECT_EQ(users[bridge_mac], bridge_username) << "Username of MAC:" << bridge_mac << "not matching";
  115 +}
  116 +
  117 +TEST(Hue, Constructor)
  118 +{
  119 + std::shared_ptr<MockHttpHandler> handler = std::make_shared<MockHttpHandler>();
  120 + Hue test_bridge(bridge_ip, bridge_username, handler);
  121 +
  122 + EXPECT_EQ(test_bridge.getBridgeIP(), bridge_ip) << "Bridge IP not matching";
  123 + EXPECT_EQ(test_bridge.getUsername(), bridge_username) << "Bridge username not matching";
  124 +}
  125 +
  126 +TEST(Hue, requestUsername)
  127 +{
  128 + std::shared_ptr<MockHttpHandler> handler = std::make_shared<MockHttpHandler>();
  129 + Json::Value request;
  130 + request["devicetype"] = "HuePlusPlus#User";
  131 +
  132 + Json::Value user_ret_uns;
  133 + user_ret_uns = Json::Value(Json::arrayValue);
  134 + user_ret_uns[0] = Json::Value(Json::objectValue);
  135 + user_ret_uns[0]["error"] = Json::Value(Json::objectValue);
  136 + user_ret_uns[0]["error"]["type"] = 101;
  137 + user_ret_uns[0]["error"]["address"] = "";
  138 + user_ret_uns[0]["error"]["description"] = "link button not pressed";
  139 +
  140 + EXPECT_CALL(*handler, GETJson("/api", request, bridge_ip, 80))
  141 + .Times(::testing::AtLeast(1))
  142 + .WillRepeatedly(::testing::Return(user_ret_uns));
  143 +
  144 + Hue test_bridge(bridge_ip, "", handler);
  145 +
  146 + test_bridge.requestUsername(test_bridge.getBridgeIP());
  147 + EXPECT_EQ(test_bridge.getUsername(), "") << "Bridge username not matching";
  148 +
  149 + Json::Value user_ret_suc;
  150 + user_ret_suc = Json::Value(Json::arrayValue);
  151 + user_ret_suc[0] = Json::Value(Json::objectValue);
  152 + user_ret_suc[0]["success"] = Json::Value(Json::objectValue);
  153 + user_ret_suc[0]["success"]["username"] = bridge_username;
  154 + EXPECT_CALL(*handler, GETJson("/api", request, bridge_ip, 80))
  155 + .Times(1)
  156 + .WillRepeatedly(::testing::Return(user_ret_suc));
  157 +
  158 + test_bridge = Hue(bridge_ip, "", handler);
  159 +
  160 + test_bridge.requestUsername(test_bridge.getBridgeIP());
  161 +
  162 + EXPECT_EQ(test_bridge.getBridgeIP(), bridge_ip) << "Bridge IP not matching";
  163 + EXPECT_EQ(test_bridge.getUsername(), bridge_username) << "Bridge username not matching";
  164 +}
  165 +
  166 +TEST(Hue, setIP)
  167 +{
  168 + std::shared_ptr<MockHttpHandler> handler = std::make_shared<MockHttpHandler>();
  169 + Hue test_bridge(bridge_ip, "", handler);
  170 + EXPECT_EQ(test_bridge.getBridgeIP(), bridge_ip) << "Bridge IP not matching after initialization";
  171 + test_bridge.setIP("192.168.2.112");
  172 + EXPECT_EQ(test_bridge.getBridgeIP(), "192.168.2.112") << "Bridge IP not matching after setting it";
  173 +}
  174 +
  175 +TEST(Hue, getLight)
  176 +{
  177 + std::shared_ptr<MockHttpHandler> handler = std::make_shared<MockHttpHandler>();
  178 + Json::Value empty_json_obj(Json::objectValue);
  179 + EXPECT_CALL(*handler, GETJson("/api/"+bridge_username, empty_json_obj, bridge_ip, 80))
  180 + .Times(1);
  181 +
  182 + Hue test_bridge(bridge_ip, bridge_username, handler);
  183 +
  184 + // Test exception
  185 + ASSERT_THROW(test_bridge.getLight(1), std::runtime_error);
  186 +
  187 + Json::Value hue_bridge_state;
  188 + hue_bridge_state["lights"] = Json::Value(Json::objectValue);
  189 + hue_bridge_state["lights"]["1"] = Json::Value(Json::objectValue);
  190 + hue_bridge_state["lights"]["1"]["state"] = Json::Value(Json::objectValue);
  191 + hue_bridge_state["lights"]["1"]["state"]["on"] = true;
  192 + hue_bridge_state["lights"]["1"]["state"]["bri"] = 254;
  193 + hue_bridge_state["lights"]["1"]["state"]["ct"] = 366;
  194 + hue_bridge_state["lights"]["1"]["state"]["alert"] = "none";
  195 + hue_bridge_state["lights"]["1"]["state"]["colormode"] = "ct";
  196 + hue_bridge_state["lights"]["1"]["state"]["reachable"] = true;
  197 + hue_bridge_state["lights"]["1"]["swupdate"] = Json::Value(Json::objectValue);
  198 + hue_bridge_state["lights"]["1"]["swupdate"]["state"] = "noupdates";
  199 + hue_bridge_state["lights"]["1"]["swupdate"]["lastinstall"] = Json::nullValue;
  200 + hue_bridge_state["lights"]["1"]["type"] = "Color temperature light";
  201 + hue_bridge_state["lights"]["1"]["name"] = "Hue ambiance lamp 1";
  202 + hue_bridge_state["lights"]["1"]["modelid"] = "LTW001";
  203 + hue_bridge_state["lights"]["1"]["manufacturername"] = "Philips";
  204 + hue_bridge_state["lights"]["1"]["uniqueid"] = "00:00:00:00:00:00:00:00-00";
  205 + hue_bridge_state["lights"]["1"]["swversion"] = "5.50.1.19085";
  206 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username, empty_json_obj, bridge_ip, 80))
  207 + .Times(1)
  208 + .WillOnce(::testing::Return(hue_bridge_state));
  209 +
  210 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username + "/lights/1", empty_json_obj, bridge_ip, 80))
  211 + .Times(3)
  212 + .WillRepeatedly(::testing::Return(hue_bridge_state["lights"]["1"]));
  213 +
  214 + // Test when correct data is sent
  215 + HueLight test_light_1 = test_bridge.getLight(1);
  216 + EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");
  217 + EXPECT_EQ(test_light_1.getColorType(), ColorType::TEMPERATURE);
  218 +
  219 + // Test again to check whether light is returned directly -> interesting for code coverage test
  220 + test_light_1 = test_bridge.getLight(1);
  221 + EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");
  222 + EXPECT_EQ(test_light_1.getColorType(), ColorType::TEMPERATURE);
  223 +
  224 +
  225 +
  226 + // more coverage stuff
  227 + hue_bridge_state["lights"]["1"]["modelid"] = "LCT001";
  228 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username, empty_json_obj, bridge_ip, 80))
  229 + .Times(1)
  230 + .WillOnce(::testing::Return(hue_bridge_state));
  231 +
  232 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username + "/lights/1", empty_json_obj, bridge_ip, 80))
  233 + .Times(2)
  234 + .WillRepeatedly(::testing::Return(hue_bridge_state["lights"]["1"]));
  235 + test_bridge = Hue(bridge_ip, bridge_username, handler);
  236 +
  237 + // Test when correct data is sent
  238 + test_light_1 = test_bridge.getLight(1);
  239 + EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");
  240 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_B);
  241 +
  242 +
  243 + hue_bridge_state["lights"]["1"]["modelid"] = "LCT010";
  244 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username, empty_json_obj, bridge_ip, 80))
  245 + .Times(1)
  246 + .WillOnce(::testing::Return(hue_bridge_state));
  247 +
  248 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username + "/lights/1", empty_json_obj, bridge_ip, 80))
  249 + .Times(2)
  250 + .WillRepeatedly(::testing::Return(hue_bridge_state["lights"]["1"]));
  251 + test_bridge = Hue(bridge_ip, bridge_username, handler);
  252 +
  253 + // Test when correct data is sent
  254 + test_light_1 = test_bridge.getLight(1);
  255 + EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");
  256 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_C);
  257 +
  258 +
  259 + hue_bridge_state["lights"]["1"]["modelid"] = "LST001";
  260 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username, empty_json_obj, bridge_ip, 80))
  261 + .Times(1)
  262 + .WillOnce(::testing::Return(hue_bridge_state));
  263 +
  264 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username + "/lights/1", empty_json_obj, bridge_ip, 80))
  265 + .Times(2)
  266 + .WillRepeatedly(::testing::Return(hue_bridge_state["lights"]["1"]));
  267 + test_bridge = Hue(bridge_ip, bridge_username, handler);
  268 +
  269 + // Test when correct data is sent
  270 + test_light_1 = test_bridge.getLight(1);
  271 + EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");
  272 + EXPECT_EQ(test_light_1.getColorType(), ColorType::GAMUT_A);
  273 +
  274 +
  275 + hue_bridge_state["lights"]["1"]["modelid"] = "LWB004";
  276 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username, empty_json_obj, bridge_ip, 80))
  277 + .Times(1)
  278 + .WillOnce(::testing::Return(hue_bridge_state));
  279 +
  280 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username + "/lights/1", empty_json_obj, bridge_ip, 80))
  281 + .Times(2)
  282 + .WillRepeatedly(::testing::Return(hue_bridge_state["lights"]["1"]));
  283 + test_bridge = Hue(bridge_ip, bridge_username, handler);
  284 +
  285 + // Test when correct data is sent
  286 + test_light_1 = test_bridge.getLight(1);
  287 + EXPECT_EQ(test_light_1.getName(), "Hue ambiance lamp 1");
  288 + EXPECT_EQ(test_light_1.getColorType(), ColorType::NONE);
  289 +
  290 +
  291 + hue_bridge_state["lights"]["1"]["modelid"] = "ABC000";
  292 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username, empty_json_obj, bridge_ip, 80))
  293 + .Times(1)
  294 + .WillOnce(::testing::Return(hue_bridge_state));
  295 + test_bridge = Hue(bridge_ip, bridge_username, handler);
  296 +
  297 + ASSERT_THROW(test_bridge.getLight(1), std::runtime_error);
  298 +
  299 +}
  300 +
  301 +TEST(Hue, removeLight)
  302 +{
  303 + std::shared_ptr<MockHttpHandler> handler = std::make_shared<MockHttpHandler>();
  304 + Json::Value empty_json_obj(Json::objectValue);
  305 + Json::Value hue_bridge_state;
  306 + hue_bridge_state["lights"] = Json::Value(Json::objectValue);
  307 + hue_bridge_state["lights"]["1"] = Json::Value(Json::objectValue);
  308 + hue_bridge_state["lights"]["1"]["state"] = Json::Value(Json::objectValue);
  309 + hue_bridge_state["lights"]["1"]["state"]["on"] = true;
  310 + hue_bridge_state["lights"]["1"]["state"]["bri"] = 254;
  311 + hue_bridge_state["lights"]["1"]["state"]["ct"] = 366;
  312 + hue_bridge_state["lights"]["1"]["state"]["alert"] = "none";
  313 + hue_bridge_state["lights"]["1"]["state"]["colormode"] = "ct";
  314 + hue_bridge_state["lights"]["1"]["state"]["reachable"] = true;
  315 + hue_bridge_state["lights"]["1"]["swupdate"] = Json::Value(Json::objectValue);
  316 + hue_bridge_state["lights"]["1"]["swupdate"]["state"] = "noupdates";
  317 + hue_bridge_state["lights"]["1"]["swupdate"]["lastinstall"] = Json::nullValue;
  318 + hue_bridge_state["lights"]["1"]["type"] = "Color temperature light";
  319 + hue_bridge_state["lights"]["1"]["name"] = "Hue ambiance lamp 1";
  320 + hue_bridge_state["lights"]["1"]["modelid"] = "LTW001";
  321 + hue_bridge_state["lights"]["1"]["manufacturername"] = "Philips";
  322 + hue_bridge_state["lights"]["1"]["uniqueid"] = "00:00:00:00:00:00:00:00-00";
  323 + hue_bridge_state["lights"]["1"]["swversion"] = "5.50.1.19085";
  324 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username, empty_json_obj, bridge_ip, 80))
  325 + .Times(1)
  326 + .WillOnce(::testing::Return(hue_bridge_state));
  327 +
  328 + Hue test_bridge(bridge_ip, bridge_username, handler);
  329 +
  330 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username + "/lights/1", empty_json_obj, bridge_ip, 80))
  331 + .Times(1)
  332 + .WillRepeatedly(::testing::Return(hue_bridge_state["lights"]["1"]));
  333 +
  334 + Json::Value return_answer;
  335 + return_answer = Json::Value(Json::arrayValue);
  336 + return_answer[0] = Json::Value(Json::objectValue);
  337 + return_answer[0]["success"] = "/lights/1 deleted";
  338 + EXPECT_CALL(*handler, DELETEJson("/api/" + bridge_username + "/lights/1", empty_json_obj, bridge_ip, 80))
  339 + .Times(2)
  340 + .WillOnce(::testing::Return(return_answer));
  341 +
  342 + // Test when correct data is sent
  343 + HueLight test_light_1 = test_bridge.getLight(1);
  344 +
  345 + EXPECT_EQ(test_bridge.removeLight(1), true);
  346 +
  347 + EXPECT_EQ(test_bridge.removeLight(1), false);
  348 +}
  349 +
  350 +TEST(Hue, getAllLights)
  351 +{
  352 + std::shared_ptr<MockHttpHandler> handler = std::make_shared<MockHttpHandler>();
  353 + Json::Value empty_json_obj(Json::objectValue);
  354 + Json::Value hue_bridge_state;
  355 + hue_bridge_state["lights"] = Json::Value(Json::objectValue);
  356 + hue_bridge_state["lights"]["1"] = Json::Value(Json::objectValue);
  357 + hue_bridge_state["lights"]["1"]["state"] = Json::Value(Json::objectValue);
  358 + hue_bridge_state["lights"]["1"]["state"]["on"] = true;
  359 + hue_bridge_state["lights"]["1"]["state"]["bri"] = 254;
  360 + hue_bridge_state["lights"]["1"]["state"]["ct"] = 366;
  361 + hue_bridge_state["lights"]["1"]["state"]["alert"] = "none";
  362 + hue_bridge_state["lights"]["1"]["state"]["colormode"] = "ct";
  363 + hue_bridge_state["lights"]["1"]["state"]["reachable"] = true;
  364 + hue_bridge_state["lights"]["1"]["swupdate"] = Json::Value(Json::objectValue);
  365 + hue_bridge_state["lights"]["1"]["swupdate"]["state"] = "noupdates";
  366 + hue_bridge_state["lights"]["1"]["swupdate"]["lastinstall"] = Json::nullValue;
  367 + hue_bridge_state["lights"]["1"]["type"] = "Color temperature light";
  368 + hue_bridge_state["lights"]["1"]["name"] = "Hue ambiance lamp 1";
  369 + hue_bridge_state["lights"]["1"]["modelid"] = "LTW001";
  370 + hue_bridge_state["lights"]["1"]["manufacturername"] = "Philips";
  371 + hue_bridge_state["lights"]["1"]["uniqueid"] = "00:00:00:00:00:00:00:00-00";
  372 + hue_bridge_state["lights"]["1"]["swversion"] = "5.50.1.19085";
  373 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username, empty_json_obj, bridge_ip, 80))
  374 + .Times(2)
  375 + .WillRepeatedly(::testing::Return(hue_bridge_state));
  376 +
  377 + EXPECT_CALL(*handler, GETJson("/api/" + bridge_username + "/lights/1", empty_json_obj, bridge_ip, 80))
  378 + .Times(2)
  379 + .WillRepeatedly(::testing::Return(hue_bridge_state["lights"]["1"]));
  380 +
  381 + Hue test_bridge(bridge_ip, bridge_username, handler);
  382 +
  383 + std::vector<std::reference_wrapper<HueLight>> test_lights = test_bridge.getAllLights();
  384 + EXPECT_EQ(test_lights[0].get().getName(), "Hue ambiance lamp 1");
  385 + EXPECT_EQ(test_lights[0].get().getColorType(), ColorType::TEMPERATURE);
  386 +}
  387 +
  388 +TEST(Hue, refreshState)
  389 +{
  390 + std::shared_ptr<MockHttpHandler> handler = std::make_shared<MockHttpHandler>();
  391 + Hue test_bridge(bridge_ip, "", handler); // NULL as username leads to segfault
  392 +
  393 + std::vector<std::reference_wrapper<HueLight>> test_lights = test_bridge.getAllLights();
  394 + EXPECT_EQ(test_lights.size(), 0);
  395 +}
... ...
hueplusplus/test/test_Main.cpp 0 → 100755
  1 +#include <gtest/gtest.h>
  2 +
  3 +int main(int argc, char** argv)
  4 +{
  5 + ::testing::InitGoogleTest(&argc, argv);
  6 + return RUN_ALL_TESTS();
  7 +}
... ...
hueplusplus/test/testhelper.h 0 → 100755
  1 +
  2 +const std::string bridge_ip = "192.168.2.116"; //!< IP-Address of the fake hue bridge in dotted decimal notation like "192.168.2.1"
  3 +const std::string bridge_username = "83b7780291a6ceffbe0bd049104df"; //!< Username that is ussed to access the fake hue bridge
  4 +const std::string bridge_id = "111111FFFE11E111";
  5 +const std::string bridge_uuid = "1f111f11-da11-11e1-1b11-11111111e111";
  6 +const std::string bridge_mac = "11111111e111";
  7 +
  8 +const std::string brige_xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"
  9 + "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
  10 + "<specVersion>"
  11 + "<major>1</major>"
  12 + "<minor>0</minor>"
  13 + "</specVersion>"
  14 + "<URLBase>http://192.168.2.116:80/</URLBase>"
  15 + "<device>"
  16 + "<deviceType>urn:schemas-upnp-org:device:Basic:1</deviceType>"
  17 + "<friendlyName>Philips hue (192.168.2.116)</friendlyName>"
  18 + "<manufacturer>Royal Philips Electronics</manufacturer>"
  19 + "<manufacturerURL>http://www.philips.com</manufacturerURL>"
  20 + "<modelDescription>Philips hue Personal Wireless Lighting</modelDescription>"
  21 + "<modelName>Philips hue bridge 2015</modelName>"
  22 + "<modelNumber>BSB002</modelNumber>"
  23 + "<modelURL>http://www.meethue.com</modelURL>"
  24 + "<serialNumber>11111111e111</serialNumber>"
  25 + "<UDN>uuid:1f111f11-da11-11e1-1b11-11111111e111</UDN>"
  26 + "<presentationURL>index.html</presentationURL>"
  27 + "<iconList>"
  28 + "<icon>"
  29 + "<mimetype>image/png</mimetype>"
  30 + "<height>48</height>"
  31 + "<width>48</width>"
  32 + "<depth>24</depth>"
  33 + "<url>hue_logo_0.png</url>"
  34 + "</icon>"
  35 + "</iconList>"
  36 + "</device>"
  37 + "</root>";
  38 +
  39 +const std::vector<std::string> multicast_reply = {
  40 + "HTTP/1.1 200 OK\r\n"
  41 + "CACHE-CONTROL: max-age=300\r\n"
  42 + "DATE: Wed, 21 Jan 1970 05:42:21 GMT\r\n"
  43 + "EXT:\r\n"
  44 + "LOCATION: http://192.168.2.1:1900/gatedesc.xml\r\n"
  45 + "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
  46 + "01-NLS: 000c0000-0dd0-00b0-0da0-00a000e000c0\r\n"
  47 + "SERVER: Linux/2.6.36, UPnP/1.0, Portable SDK for UPnP devices/1.6.19\r\n"
  48 + "X-User-Agent: redsonic\r\n"
  49 + "ST: upnp:rootdevice\r\n"
  50 + "USN: uuid:0f0000b0-f0da-0ad0-00b0-0000000fdf00::upnp:rootdevice",
  51 +
  52 + "HTTP/1.1 200 OK\r\n"
  53 + "CACHE-CONTROL: max-age=300\r\n"
  54 + "DATE: Wed, 21 Jan 1970 05:42:21 GMT\r\n"
  55 + "EXT:\r\n"
  56 + "LOCATION: http://192.168.2.1:1900/gatedesc.xml\r\n"
  57 + "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
  58 + "01-NLS: 000c0000-0dd0-00b0-0da0-00a000e000c0\r\n"
  59 + "SERVER: Linux/2.6.36, UPnP/1.0, Portable SDK for UPnP devices/1.6.19\r\n"
  60 + "X-User-Agent: redsonic\r\n"
  61 + "ST: uuid:0f0000b0-f0da-0ad0-00b0-0000000fdf00\r\n"
  62 + "USN: uuid:0f0000b0-f0da-0ad0-00b0-0000000fdf00",
  63 +
  64 + "HTTP/1.1 200 OK\r\n"
  65 + "CACHE-CONTROL: max-age=300\r\n"
  66 + "DATE: Wed, 21 Jan 1970 05:42:21 GMT\r\n"
  67 + "EXT:\r\n"
  68 + "LOCATION: http://192.168.2.1:1900/gatedesc.xml\r\n"
  69 + "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
  70 + "01-NLS: 000c0000-0dd0-00b0-0da0-00a000e000c0\r\n"
  71 + "SERVER: Linux/2.6.36, UPnP/1.0, Portable SDK for UPnP devices/1.6.19\r\n"
  72 + "X-User-Agent: redsonic\r\n"
  73 + "ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\n"
  74 + "USN: uuid:0f0000b0-f0da-0ad0-00b0-0000000fdf00::urn:schemas-upnp-org:device:InternetGatewayDevice:1",
  75 +
  76 + "HTTP/1.1 200 OK\r\n"
  77 + "CACHE-CONTROL: max-age=300\r\n"
  78 + "DATE: Wed, 21 Jan 1970 05:42:21 GMT\r\n"
  79 + "EXT:\r\n"
  80 + "LOCATION: http://192.168.2.1:1900/gatedesc.xml\r\n"
  81 + "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
  82 + "01-NLS: 000c0000-0dd0-00b0-0da0-00a000e000c0\r\n"
  83 + "SERVER: Linux/2.6.36, UPnP/1.0, Portable SDK for UPnP devices/1.6.19\r\n"
  84 + "X-User-Agent: redsonic\r\n"
  85 + "ST: urn:schemas-upnp-org:service:Layer3Forwarding:1\r\n"
  86 + "USN: uuid:0f0000b0-f0da-0ad0-00b0-0000000fdf00::urn:schemas-upnp-org:service:Layer3Forwarding:1",
  87 +
  88 + "HTTP/1.1 200 OK\r\n"
  89 + "CACHE-CONTROL: max-age=300\r\n"
  90 + "DATE: Wed, 21 Jan 1970 05:42:21 GMT\r\n"
  91 + "EXT:\r\n"
  92 + "LOCATION: http://192.168.2.1:1900/gatedesc.xml\r\n"
  93 + "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
  94 + "01-NLS: 000c0000-0dd0-00b0-0da0-00a000e000c0\r\n"
  95 + "SERVER: Linux/2.6.36, UPnP/1.0, Portable SDK for UPnP devices/1.6.19\r\n"
  96 + "X-User-Agent: redsonic\r\n"
  97 + "ST: uuid:0f0000b0-f0da-0ad0-00b0-0000000fdf00\r\n"
  98 + "USN: uuid:0f0000b0-f0da-0ad0-00b0-0000000fdf00",
  99 +
  100 + "HTTP/1.1 200 OK\r\n"
  101 + "CACHE-CONTROL: max-age=300\r\n"
  102 + "DATE: Wed, 21 Jan 1970 05:42:21 GMT\r\n"
  103 + "EXT:\r\n"
  104 + "LOCATION: http://192.168.2.1:1900/gatedesc.xml\r\n"
  105 + "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
  106 + "01-NLS: 000c0000-0dd0-00b0-0da0-00a000e000c0\r\n"
  107 + "SERVER: Linux/2.6.36, UPnP/1.0, Portable SDK for UPnP devices/1.6.19\r\n"
  108 + "X-User-Agent: redsonic\r\n"
  109 + "ST: urn:schemas-upnp-org:device:WANDevice:1\r\n"
  110 + "USN: uuid:0f0000b0-f0da-0ad0-00b0-0000000fdf00::urn:schemas-upnp-org:device:WANDevice:1",
  111 +
  112 + "HTTP/1.1 200 OK\r\n"
  113 + "CACHE-CONTROL: max-age=300\r\n"
  114 + "DATE: Wed, 21 Jan 1970 05:42:21 GMT\r\n"
  115 + "EXT:\r\n"
  116 + "LOCATION: http://192.168.2.1:1900/gatedesc.xml\r\n"
  117 + "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
  118 + "01-NLS: 000c0000-0dd0-00b0-0da0-00a000e000c0\r\n"
  119 + "SERVER: Linux/2.6.36, UPnP/1.0, Portable SDK for UPnP devices/1.6.19\r\n"
  120 + "X-User-Agent: redsonic\r\n"
  121 + "ST: urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1\r\n"
  122 + "USN: uuid:0f0000b0-f0da-0ad0-00b0-0000000fdf00::urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1",
  123 +
  124 + "HTTP/1.1 200 OK\r\n"
  125 + "CACHE-CONTROL: max-age=300\r\n"
  126 + "DATE: Wed, 21 Jan 1970 05:42:21 GMT\r\n"
  127 + "EXT:\r\n"
  128 + "LOCATION: http://192.168.2.1:1900/gatedesc.xml\r\n"
  129 + "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
  130 + "01-NLS: 000c0000-0dd0-00b0-0da0-00a000e000c0\r\n"
  131 + "SERVER: Linux/2.6.36, UPnP/1.0, Portable SDK for UPnP devices/1.6.19\r\n"
  132 + "X-User-Agent: redsonic\r\n"
  133 + "ST: uuid:0f0000b0-f0da-0ad0-00b0-0000000fdf00\r\n"
  134 + "USN: uuid:0f0000b0-f0da-0ad0-00b0-0000000fdf00",
  135 +
  136 + "HTTP/1.1 200 OK\r\n"
  137 + "CACHE-CONTROL: max-age=300\r\n"
  138 + "DATE: Wed, 21 Jan 1970 05:42:21 GMT\r\n"
  139 + "EXT:\r\n"
  140 + "LOCATION: http://192.168.2.1:1900/gatedesc.xml\r\n"
  141 + "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
  142 + "01-NLS: 000c0000-0dd0-00b0-0da0-00a000e000c0\r\n"
  143 + "SERVER: Linux/2.6.36, UPnP/1.0, Portable SDK for UPnP devices/1.6.19\r\n"
  144 + "X-User-Agent: redsonic\r\n"
  145 + "ST: urn:schemas-upnp-org:device:WANConnectionDevice:1\r\n"
  146 + "USN: uuid:0f0000b0-f0da-0ad0-00b0-0000000fdf00::urn:schemas-upnp-org:device:WANConnectionDevice:1",
  147 +
  148 + "HTTP/1.1 200 OK\r\n"
  149 + "CACHE-CONTROL: max-age=300\r\n"
  150 + "DATE: Wed, 21 Jan 1970 05:42:21 GMT\r\n"
  151 + "EXT:\r\n"
  152 + "LOCATION: http://192.168.2.1:1900/gatedesc.xml\r\n"
  153 + "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"
  154 + "01-NLS: 000c0000-0dd0-00b0-0da0-00a000e000c0\r\n"
  155 + "SERVER: Linux/2.6.36, UPnP/1.0, Portable SDK for UPnP devices/1.6.19\r\n"
  156 + "X-User-Agent: redsonic\r\n"
  157 + "ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n"
  158 + "USN: uuid:0f0000b0-f0da-0ad0-00b0-0000000fdf00::urn:schemas-upnp-org:service:WANIPConnection:1",
  159 +
  160 + "HTTP/1.1 200 OK\r\n"
  161 + "HOST: 239.255.255.250:1900\r\n"
  162 + "EXT:\r\n"
  163 + "CACHE-CONTROL: max-age=100\r\n"
  164 + "LOCATION: http://192.168.2.116:80/description.xml\r\n"
  165 + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.21.0\r\n"
  166 + "hue-bridgeid: 111111FFFE11E111\r\n"
  167 + "ST: upnp:rootdevice\r\n"
  168 + "USN: uuid:1f111f11-da11-11e1-1b11-11111111e111::upnp:rootdevice",
  169 +
  170 + "HTTP/1.1 200 OK\r\n"
  171 + "HOST: 239.255.255.250:1900\r\n"
  172 + "EXT:\r\n"
  173 + "CACHE-CONTROL: max-age=100\r\n"
  174 + "LOCATION: http://192.168.2.116:80/description.xml\r\n"
  175 + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.21.0\r\n"
  176 + "hue-bridgeid: 111111FFFE11E111\r\n"
  177 + "ST: uuid:1f111f11-da11-11e1-1b11-11111111e111\r\n"
  178 + "USN: uuid:1f111f11-da11-11e1-1b11-11111111e111",
  179 +
  180 + "HTTP/1.1 200 OK\r\n"
  181 + "HOST: 239.255.255.250:1900\r\n"
  182 + "EXT:\r\n"
  183 + "CACHE-CONTROL: max-age=100\r\n"
  184 + "LOCATION: http://192.168.2.116:80/description.xml\r\n"
  185 + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.21.0\r\n"
  186 + "hue-bridgeid: 111111FFFE11E111\r\n"
  187 + "ST: urn:schemas-upnp-org:device:basic:1\r\n"
  188 + "USN: uuid:1f111f11-da11-11e1-1b11-11111111e111",
  189 +
  190 + "HTTP/1.1 200 OK\r\n"
  191 + "HOST: 239.255.255.250:1900\r\n"
  192 + "EXT:\r\n"
  193 + "CACHE-CONTROL: max-age=100\r\n"
  194 + "LOCATION: http://192.168.2.116:80/description.xml\r\n"
  195 + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.21.0\r\n"
  196 + "hue-bridgeid: 111111FFFE11E111\r\n"
  197 + "ST: upnp:rootdevice\r\n"
  198 + "USN: uuid:1f111f11-da11-11e1-1b11-11111111e111::upnp:rootdevice",
  199 +
  200 + "HTTP/1.1 200 OK\r\n"
  201 + "HOST: 239.255.255.250:1900\r\n"
  202 + "EXT:\r\n"
  203 + "CACHE-CONTROL: max-age=100\r\n"
  204 + "LOCATION: http://192.168.2.116:80/description.xml\r\n"
  205 + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.21.0\r\n"
  206 + "hue-bridgeid: 111111FFFE11E111\r\n"
  207 + "ST: uuid:1f111f11-da11-11e1-1b11-11111111e111\r\n"
  208 + "USN: uuid:1f111f11-da11-11e1-1b11-11111111e111",
  209 +
  210 + "HTTP/1.1 200 OK\r\n"
  211 + "HOST: 239.255.255.250:1900\r\n"
  212 + "EXT:\r\n"
  213 + "CACHE-CONTROL: max-age=100\r\n"
  214 + "LOCATION: http://192.168.2.116:80/description.xml\r\n"
  215 + "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.21.0\r\n"
  216 + "hue-bridgeid: 111111FFFE11E111\r\n"
  217 + "ST: urn:schemas-upnp-org:device:basic:1\r\n"
  218 + "USN: uuid:1f111f11-da11-11e1-1b11-11111111e111"
  219 +};
... ...