Commit eee2f0eaf84aa992439d107f1280f388eebf628e

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

Add tests for ResourceList and other missing tests.

include/hueplusplus/ResourceList.h
@@ -66,7 +66,7 @@ public: @@ -66,7 +66,7 @@ public:
66 //! Necessary if Resource is not constructible as described above. 66 //! Necessary if Resource is not constructible as described above.
67 ResourceList(const HueCommandAPI& commands, const std::string& path, 67 ResourceList(const HueCommandAPI& commands, const std::string& path,
68 std::chrono::steady_clock::duration refreshDuration, 68 std::chrono::steady_clock::duration refreshDuration,
69 - const std::function<Resource(int, const nlohmann::json&)>& factory = nullptr) 69 + const std::function<Resource(IdType, const nlohmann::json&)>& factory = nullptr)
70 : stateCache(path, commands, refreshDuration), factory(factory), path(path + '/') 70 : stateCache(path, commands, refreshDuration), factory(factory), path(path + '/')
71 {} 71 {}
72 72
@@ -230,7 +230,7 @@ private: @@ -230,7 +230,7 @@ private:
230 230
231 protected: 231 protected:
232 APICache stateCache; 232 APICache stateCache;
233 - std::function<Resource(int, const nlohmann::json&)> factory; 233 + std::function<Resource(IdType, const nlohmann::json&)> factory;
234 std::string path; 234 std::string path;
235 std::map<IdType, Resource> resources; 235 std::map<IdType, Resource> resources;
236 }; 236 };
src/Schedule.cpp
@@ -199,7 +199,7 @@ CreateSchedule&amp; CreateSchedule::setName(const std::string&amp; name) @@ -199,7 +199,7 @@ CreateSchedule&amp; CreateSchedule::setName(const std::string&amp; name)
199 199
200 CreateSchedule& CreateSchedule::setDescription(const std::string& description) 200 CreateSchedule& CreateSchedule::setDescription(const std::string& description)
201 { 201 {
202 - request["descripton"] = description; 202 + request["description"] = description;
203 return *this; 203 return *this;
204 } 204 }
205 205
test/CMakeLists.txt
@@ -40,11 +40,12 @@ set(TEST_SOURCES @@ -40,11 +40,12 @@ set(TEST_SOURCES
40 test_HueLightFactory.cpp 40 test_HueLightFactory.cpp
41 test_HueCommandAPI.cpp 41 test_HueCommandAPI.cpp
42 test_Main.cpp 42 test_Main.cpp
  43 + test_UPnP.cpp
  44 + test_ResourceList.cpp
  45 + test_Schedule.cpp
43 test_SimpleBrightnessStrategy.cpp 46 test_SimpleBrightnessStrategy.cpp
44 test_SimpleColorHueStrategy.cpp 47 test_SimpleColorHueStrategy.cpp
45 test_SimpleColorTemperatureStrategy.cpp 48 test_SimpleColorTemperatureStrategy.cpp
46 - test_UPnP.cpp  
47 - test_Schedule.cpp  
48 test_StateTransaction.cpp 49 test_StateTransaction.cpp
49 test_TimePattern.cpp) 50 test_TimePattern.cpp)
50 51
test/test_ResourceList.cpp 0 → 100644
  1 +/**
  2 + \file test_ResourceList.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/ResourceList.h"
  27 +#include "mocks/mock_HttpHandler.h"
  28 +
  29 +using namespace hueplusplus;
  30 +using namespace testing;
  31 +
  32 +class TestResource
  33 +{
  34 +public:
  35 + TestResource(int id, HueCommandAPI api, std::chrono::steady_clock::duration refreshDuration) : id(id) {}
  36 +
  37 + void refresh() {}
  38 +
  39 +public:
  40 + int id;
  41 +};
  42 +class TestResourceFactory
  43 +{
  44 +public:
  45 + void refresh() {}
  46 +};
  47 +class TestStringResource
  48 +{
  49 +public:
  50 + TestStringResource(const std::string& id, HueCommandAPI api, std::chrono::steady_clock::duration refreshDuration)
  51 + : id(id)
  52 + {}
  53 + void refresh() {}
  54 +
  55 +public:
  56 + std::string id;
  57 +};
  58 +
  59 +class TestCreateType
  60 +{
  61 +public:
  62 + MOCK_CONST_METHOD0(getRequest, nlohmann::json());
  63 +};
  64 +
  65 +TEST(ResourceList, refresh)
  66 +{
  67 + auto handler = std::make_shared<MockHttpHandler>();
  68 + HueCommandAPI commands(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
  69 +
  70 + const std::string path = "/resources";
  71 + {
  72 + ResourceList<TestResource, int> list(commands, path, std::chrono::steady_clock::duration::max());
  73 + EXPECT_CALL(*handler,
  74 + GETJson("/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  75 + .Times(2)
  76 + .WillRepeatedly(Return(nlohmann::json::object()));
  77 + list.refresh();
  78 + list.refresh();
  79 + Mock::VerifyAndClearExpectations(handler.get());
  80 + }
  81 + {
  82 + auto baseCache = std::make_shared<APICache>("", commands, std::chrono::steady_clock::duration::max());
  83 + ResourceList<TestResource, int> list(baseCache, "resources", std::chrono::steady_clock::duration::max());
  84 + InSequence s;
  85 + EXPECT_CALL(
  86 + *handler, GETJson("/api/" + getBridgeUsername(), nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  87 + .WillOnce(Return(nlohmann::json {{"resources", nlohmann::json::object()}}));
  88 + EXPECT_CALL(*handler,
  89 + GETJson("/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  90 + .Times(2)
  91 + .WillRepeatedly(Return(nlohmann::json::object()));
  92 + list.refresh();
  93 + list.refresh();
  94 + list.refresh();
  95 + Mock::VerifyAndClearExpectations(handler.get());
  96 + }
  97 +}
  98 +
  99 +TEST(ResourceList, get)
  100 +{
  101 + auto handler = std::make_shared<MockHttpHandler>();
  102 + HueCommandAPI commands(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
  103 +
  104 + const std::string path = "/resources";
  105 + // No factory
  106 + {
  107 + const int id = 2;
  108 + const nlohmann::json response = {{std::to_string(id), {{"resource", "state"}}}};
  109 + ResourceList<TestResource, int> list(commands, path, std::chrono::steady_clock::duration::max());
  110 + EXPECT_CALL(*handler,
  111 + GETJson("/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  112 + .WillOnce(Return(response));
  113 +
  114 + TestResource& r = list.get(id);
  115 + EXPECT_EQ(id, r.id);
  116 + TestResource& r2 = list.get(id);
  117 + EXPECT_EQ(id, r2.id);
  118 + }
  119 + // With factory
  120 + {
  121 + const int id = 2;
  122 + const nlohmann::json state = {{"resource", "state"}};
  123 + const nlohmann::json response = {{std::to_string(id), state}};
  124 +
  125 + MockFunction<TestResource(int, const nlohmann::json&)> factory;
  126 + EXPECT_CALL(factory, Call(id, state))
  127 + .WillOnce(Return(TestResource(id, commands, std::chrono::steady_clock::duration::max())));
  128 +
  129 + ResourceList<TestResource, int> list(
  130 + commands, path, std::chrono::steady_clock::duration::max(), factory.AsStdFunction());
  131 + EXPECT_CALL(*handler,
  132 + GETJson("/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  133 + .WillOnce(Return(response));
  134 +
  135 + TestResource& r = list.get(id);
  136 + EXPECT_EQ(id, r.id);
  137 + }
  138 + // String id without factory
  139 + {
  140 + const std::string id = "id-2";
  141 + const nlohmann::json response = {{id, {{"resource", "state"}}}};
  142 + ResourceList<TestStringResource, std::string> list(commands, path, std::chrono::steady_clock::duration::max());
  143 + EXPECT_CALL(*handler,
  144 + GETJson("/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  145 + .WillOnce(Return(response));
  146 +
  147 + TestStringResource& r = list.get(id);
  148 + EXPECT_EQ(id, r.id);
  149 + TestStringResource& r2 = list.get(id);
  150 + EXPECT_EQ(id, r2.id);
  151 + }
  152 +
  153 + {
  154 + ResourceList<TestResourceFactory, int> list(commands, path, std::chrono::steady_clock::duration::max());
  155 +
  156 + const int id = 2;
  157 + const nlohmann::json response = { {std::to_string(id), {{"resource", "state"}}} };
  158 + EXPECT_CALL(*handler,
  159 + GETJson("/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  160 + .WillOnce(Return(response));
  161 + EXPECT_THROW(list.get(id), HueException);
  162 + }
  163 + {
  164 + ResourceList<TestResourceFactory, int> list(commands, path, std::chrono::steady_clock::duration::max(),
  165 + [](int, const nlohmann::json&) {return TestResourceFactory(); });
  166 +
  167 + const int id = 2;
  168 + const nlohmann::json response = { {std::to_string(id), {{"resource", "state"}}} };
  169 + EXPECT_CALL(*handler,
  170 + GETJson("/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  171 + .WillOnce(Return(response));
  172 + EXPECT_NO_THROW(list.get(id));
  173 + }
  174 +}
  175 +
  176 +TEST(ResourceList, exists)
  177 +{
  178 + auto handler = std::make_shared<MockHttpHandler>();
  179 + HueCommandAPI commands(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
  180 +
  181 + const std::string path = "/resources";
  182 + const int id = 2;
  183 + const nlohmann::json response = {{std::to_string(id), {{"resource", "state"}}}};
  184 + ResourceList<TestResource, int> list(commands, path, std::chrono::steady_clock::duration::max());
  185 + EXPECT_CALL(*handler,
  186 + GETJson("/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  187 + .WillOnce(Return(response));
  188 + list.refresh();
  189 + EXPECT_TRUE(list.exists(id));
  190 + EXPECT_FALSE(list.exists(4));
  191 +}
  192 +
  193 +TEST(ResourceList, getAll)
  194 +{
  195 + auto handler = std::make_shared<MockHttpHandler>();
  196 + HueCommandAPI commands(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
  197 +
  198 + const std::string path = "/resources";
  199 +
  200 + const int id = 2;
  201 + const nlohmann::json response = {{std::to_string(id), {{"resource", "state"}}}};
  202 + ResourceList<TestResource, int> list(commands, path, std::chrono::steady_clock::duration::max());
  203 + EXPECT_CALL(*handler,
  204 + GETJson("/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  205 + .WillOnce(Return(response));
  206 +
  207 + auto resources = list.getAll();
  208 + EXPECT_THAT(resources, ElementsAre(testing::Field("id", &TestResource::id, Eq(id))));
  209 +
  210 + const int id2 = 3;
  211 + const nlohmann::json response2 = {{std::to_string(id), {{"r", "s"}}}, {std::to_string(id2), {{"b", "c"}}}};
  212 +
  213 + EXPECT_CALL(*handler,
  214 + GETJson("/api/" + getBridgeUsername() + path, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  215 + .WillOnce(Return(response2));
  216 + list.refresh();
  217 + auto resources2 = list.getAll();
  218 + EXPECT_THAT(resources2,
  219 + ElementsAre(testing::Field("id", &TestResource::id, Eq(id)), testing::Field("id", &TestResource::id, Eq(id2))));
  220 +}
  221 +
  222 +TEST(ResourceList, remove)
  223 +{
  224 + auto handler = std::make_shared<MockHttpHandler>();
  225 + HueCommandAPI commands(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
  226 +
  227 + const std::string path = "/resources";
  228 + const int id = 2;
  229 + const std::string requestPath = path + "/" + std::to_string(id);
  230 + const nlohmann::json response = {{{"success", requestPath + " deleted"}}};
  231 + ResourceList<TestResource, int> list(commands, path, std::chrono::steady_clock::duration::max());
  232 + EXPECT_CALL(*handler,
  233 + DELETEJson(
  234 + "/api/" + getBridgeUsername() + requestPath, nlohmann::json::object(), getBridgeIp(), getBridgePort()))
  235 + .WillOnce(Return(response))
  236 + .WillOnce(Return(nlohmann::json()));
  237 + EXPECT_TRUE(list.remove(id));
  238 + EXPECT_FALSE(list.remove(id));
  239 +}
  240 +
  241 +TEST(CreateableResourceList, create)
  242 +{
  243 + auto handler = std::make_shared<MockHttpHandler>();
  244 + HueCommandAPI commands(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler);
  245 +
  246 + const std::string path = "/resources";
  247 + const nlohmann::json response = { {{"success", {{"id", path + "/2"}}}} };
  248 + const nlohmann::json request = { {"name", "bla"} };
  249 + CreateableResourceList<TestResource, int, TestCreateType> list(commands, path, std::chrono::steady_clock::duration::max());
  250 + EXPECT_CALL(*handler, POSTJson(
  251 + "/api/" + getBridgeUsername() + path, request, getBridgeIp(), getBridgePort()))
  252 + .WillOnce(Return(response))
  253 + .WillOnce(Return(nlohmann::json()));
  254 + TestCreateType params;
  255 + EXPECT_CALL(params, getRequest()).Times(2).WillRepeatedly(Return(request));
  256 + EXPECT_EQ(2, list.create(params));
  257 + EXPECT_EQ(0, list.create(params));
  258 +}
0 \ No newline at end of file 259 \ No newline at end of file
test/test_Schedule.cpp
@@ -287,4 +287,69 @@ TEST_F(ScheduleTest, setAutodelete) @@ -287,4 +287,69 @@ TEST_F(ScheduleTest, setAutodelete)
287 .WillOnce(Return(response)); 287 .WillOnce(Return(response));
288 expectGetState(id); 288 expectGetState(id);
289 schedule.setAutodelete(autodelete); 289 schedule.setAutodelete(autodelete);
290 -}  
291 \ No newline at end of file 290 \ No newline at end of file
  291 +}
  292 +
  293 +TEST(CreateSchedule, setName)
  294 +{
  295 + const std::string name = "New schedule";
  296 + const nlohmann::json request = {{"name", name}};
  297 + EXPECT_EQ(request, CreateSchedule().setName(name).getRequest());
  298 +}
  299 +
  300 +TEST(CreateSchedule, setDescription)
  301 +{
  302 + const std::string description = "New schedule description";
  303 + {
  304 + const nlohmann::json request = {{"description", description}};
  305 + EXPECT_EQ(request, CreateSchedule().setDescription(description).getRequest());
  306 + }
  307 + {
  308 + const std::string name = "New schedule name";
  309 + const nlohmann::json request = {{"name", name}, {"description", description}};
  310 + EXPECT_EQ(request, CreateSchedule().setName(name).setDescription(description).getRequest());
  311 + }
  312 +}
  313 +
  314 +TEST(CreateSchedule, setCommand)
  315 +{
  316 + const nlohmann::json commandJson = {{"address", "/api/asdf"}, {"method", "PUT"}, {"body", {}}};
  317 + ScheduleCommand command {commandJson};
  318 + const nlohmann::json request = {{"command", commandJson}};
  319 + EXPECT_EQ(request, CreateSchedule().setCommand(command).getRequest());
  320 +}
  321 +
  322 +TEST(CreateSchedule, setTime)
  323 +{
  324 + const time::AbsoluteTime time(std::chrono::system_clock::now());
  325 + const nlohmann::json request = {{"localtime", time.toString()}};
  326 + EXPECT_EQ(request, CreateSchedule().setTime(time::TimePattern(time)).getRequest());
  327 +}
  328 +
  329 +TEST(CreateSchedule, setStatus)
  330 +{
  331 + {
  332 + const nlohmann::json request = {{"status", "enabled"}};
  333 + EXPECT_EQ(request, CreateSchedule().setStatus(Schedule::Status::enabled).getRequest());
  334 + }
  335 + {
  336 + const nlohmann::json request = {{"status", "disabled"}};
  337 + EXPECT_EQ(request, CreateSchedule().setStatus(Schedule::Status::disabled).getRequest());
  338 + }
  339 +}
  340 +
  341 +TEST(CreateSchedule, setAutodelete)
  342 +{
  343 + {
  344 + const nlohmann::json request = { {"autodelete", true} };
  345 + EXPECT_EQ(request, CreateSchedule().setAutodelete(true).getRequest());
  346 + }
  347 +}
  348 +
  349 +
  350 +TEST(CreateSchedule, setRecycle)
  351 +{
  352 + {
  353 + const nlohmann::json request = {{"recycle", true}};
  354 + EXPECT_EQ(request, CreateSchedule().setRecycle(true).getRequest());
  355 + }
  356 +}
test/test_TimePattern.cpp
@@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
20 **/ 20 **/
21 21
22 #include <gtest/gtest.h> 22 #include <gtest/gtest.h>
  23 +#include <hueplusplus/HueException.h>
23 #include <hueplusplus/TimePattern.h> 24 #include <hueplusplus/TimePattern.h>
24 25
25 using namespace hueplusplus::time; 26 using namespace hueplusplus::time;
@@ -334,6 +335,50 @@ TEST(TimePattern, Undefined) @@ -334,6 +335,50 @@ TEST(TimePattern, Undefined)
334 TimePattern pattern = TimePattern::parse("none"); 335 TimePattern pattern = TimePattern::parse("none");
335 EXPECT_EQ(TimePattern::Type::undefined, pattern.getType()); 336 EXPECT_EQ(TimePattern::Type::undefined, pattern.getType());
336 } 337 }
  338 + EXPECT_THROW(TimePattern::parse("bla"), hueplusplus::HueException);
  339 +}
  340 +
  341 +TEST(TimePattern, CopyConstructor)
  342 +{
  343 + {
  344 + TimePattern pattern;
  345 + TimePattern copy = pattern;
  346 + EXPECT_EQ(TimePattern::Type::undefined, copy.getType());
  347 + }
  348 + {
  349 + const AbsoluteTime abs(system_clock::now());
  350 + const TimePattern pattern(abs);
  351 + const TimePattern copy(pattern);
  352 + ASSERT_EQ(TimePattern::Type::absolute, copy.getType());
  353 + EXPECT_EQ(abs.getBaseTime(), copy.asAbsolute().getBaseTime());
  354 + }
  355 + {
  356 + const RecurringTime rec(12h + 30min, Weekdays::monday(), 1h);
  357 + const TimePattern pattern(rec);
  358 + const TimePattern copy(pattern);
  359 + ASSERT_EQ(TimePattern::Type::recurring, copy.getType());
  360 + EXPECT_EQ(rec.getDaytime(), copy.asRecurring().getDaytime());
  361 + EXPECT_EQ(rec.getWeekdays(), copy.asRecurring().getWeekdays());
  362 + EXPECT_EQ(rec.getRandomVariation(), copy.asRecurring().getRandomVariation());
  363 + }
  364 + {
  365 + const TimeInterval interval(12h + 30min, 13h + 20min, Weekdays::friday());
  366 + const TimePattern pattern(interval);
  367 + const TimePattern copy(pattern);
  368 + ASSERT_EQ(TimePattern::Type::interval, copy.getType());
  369 + EXPECT_EQ(interval.getStartTime(), copy.asInterval().getStartTime());
  370 + EXPECT_EQ(interval.getEndTime(), copy.asInterval().getEndTime());
  371 + EXPECT_EQ(interval.getWeekdays(), copy.asInterval().getWeekdays());
  372 + }
  373 + {
  374 + const Timer timer(1h + 30min, 5, 20s);
  375 + const TimePattern pattern(timer);
  376 + const TimePattern copy(pattern);
  377 + ASSERT_EQ(TimePattern::Type::timer, copy.getType());
  378 + EXPECT_EQ(timer.getExpiryTime(), copy.asTimer().getExpiryTime());
  379 + EXPECT_EQ(timer.getRandomVariation(), copy.asTimer().getRandomVariation());
  380 + EXPECT_EQ(timer.getNumberOfExecutions(), copy.asTimer().getNumberOfExecutions());
  381 + }
337 } 382 }
338 383
339 TEST(TimePattern, Absolute) 384 TEST(TimePattern, Absolute)