/** \file test_Rule.cpp Copyright Notice\n Copyright (C) 2020 Jan Rogall - developer\n This file is part of hueplusplus. hueplusplus is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. hueplusplus is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with hueplusplus. If not, see . **/ #include #include #include "testhelper.h" #include "mocks/mock_HttpHandler.h" using namespace hueplusplus; using namespace testing; TEST(Condition, Constructor) { const std::string address = "/api/abcd/test"; const std::string value = "test value"; Condition condition(address, Condition::Operator::eq, value); EXPECT_EQ(address, condition.getAddress()); EXPECT_EQ(Condition::Operator::eq, condition.getOperator()); EXPECT_EQ(value, condition.getValue()); } TEST(Condition, toJson) { Condition condition("/abcd", Condition::Operator::lt, "3"); EXPECT_EQ(nlohmann::json({{"address", "/abcd"}, {"operator", "lt"}, {"value", "3"}}), condition.toJson()); } TEST(Condition, parse) { Condition condition = Condition::parse(nlohmann::json({{"address", "/abcd"}, {"operator", "lt"}, {"value", "3"}})); EXPECT_EQ("/abcd", condition.getAddress()); EXPECT_EQ(Condition::Operator::lt, condition.getOperator()); EXPECT_EQ("3", condition.getValue()); EXPECT_THROW(Condition::parse(nlohmann::json({{"address", "/abcd"}, {"operator", "something"}, {"value", "3"}})), HueException); } TEST(Condition, operatorString) { using Op = Condition::Operator; std::map values = {{Op::eq, "eq"}, {Op::gt, "gt"}, {Op::lt, "lt"}, {Op::dx, "dx"}, {Op::ddx, "ddx"}, {Op::stable, "stable"}, {Op::notStable, "not stable"}, {Op::in, "in"}, {Op::notIn, "not in"}}; for (const auto& pair : values) { Condition c("", pair.first, ""); // Check that correct string is EXPECT_EQ(pair.second, c.toJson().at("operator")); EXPECT_EQ(pair.first, Condition::parse(nlohmann::json {{"address", "/abcd"}, {"operator", pair.second}, {"value", "3"}}) .getOperator()); } } class RuleTest : public Test { protected: std::shared_ptr handler; HueCommandAPI commands; nlohmann::json ruleState; RuleTest() : handler(std::make_shared()), commands(getBridgeIp(), getBridgePort(), getBridgeUsername(), handler), ruleState({{"name", "Rule 1"}, {"owner", "testOwner"}, {"created", "2020-06-01T10:00:00"}, {"lasttriggered", "none"}, {"timestriggered", 0}, {"status", "enabled"}, {"conditions", {{{"address", "testAddress"}, {"operator", "eq"}, {"value", "10"}}}}, {"actions", {{{"address", "testAction"}, {"method", "PUT"}, {"body", {}}}}}}) { } void expectGetState(int id) { EXPECT_CALL(*handler, GETJson("/api/" + getBridgeUsername() + "/rules/" + std::to_string(id), _, getBridgeIp(), getBridgePort())) .WillOnce(Return(ruleState)); } Rule getRule(int id = 1) { expectGetState(id); return Rule(id, commands, std::chrono::steady_clock::duration::max(), nullptr); } }; TEST_F(RuleTest, getName) { const std::string name = "Rule name"; ruleState["name"] = name; const Rule rule = getRule(); EXPECT_EQ(name, rule.getName()); } TEST_F(RuleTest, setName) { Rule rule = getRule(); const std::string name = "Test rule"; nlohmann::json request = {{"name", name}}; nlohmann::json response = {{"success", {"/rules/1/name", name}}}; EXPECT_CALL(*handler, PUTJson("/api/" + getBridgeUsername() + "/rules/1", request, getBridgeIp(), getBridgePort())) .WillOnce(Return(response)); expectGetState(1); rule.setName(name); } TEST_F(RuleTest, getCreated) { const std::string timestamp = "2020-06-01T10:00:00"; ruleState["created"] = timestamp; const Rule rule = getRule(); EXPECT_EQ(time::AbsoluteTime::parseUTC(timestamp).getBaseTime(), rule.getCreated().getBaseTime()); } TEST_F(RuleTest, getLastTriggered) { const std::string timestamp = "2020-06-01T10:00:00"; ruleState["lasttriggered"] = timestamp; const Rule rule = getRule(); EXPECT_EQ(time::AbsoluteTime::parseUTC(timestamp).getBaseTime(), rule.getLastTriggered().getBaseTime()); ruleState["lasttriggered"] = "none"; const Rule rule2 = getRule(); EXPECT_EQ(std::chrono::system_clock::time_point(std::chrono::seconds(0)), rule2.getLastTriggered().getBaseTime()); } TEST_F(RuleTest, getTimesTriggered) { const int times = 20; ruleState["timestriggered"] = times; EXPECT_EQ(times, getRule().getTimesTriggered()); } TEST_F(RuleTest, isEnabled) { ruleState["status"] = "enabled"; EXPECT_TRUE(getRule().isEnabled()); ruleState["status"] = "disabled"; EXPECT_FALSE(getRule().isEnabled()); } TEST_F(RuleTest, setEnabled) { Rule rule = getRule(); { nlohmann::json request = {{"status", "enabled"}}; nlohmann::json response = {{"success", {"/rules/1/status", "enabled"}}}; EXPECT_CALL( *handler, PUTJson("/api/" + getBridgeUsername() + "/rules/1", request, getBridgeIp(), getBridgePort())) .WillOnce(Return(response)); expectGetState(1); rule.setEnabled(true); } { nlohmann::json request = {{"status", "disabled"}}; nlohmann::json response = {{"success", {"/rules/1/status", "disabled"}}}; EXPECT_CALL( *handler, PUTJson("/api/" + getBridgeUsername() + "/rules/1", request, getBridgeIp(), getBridgePort())) .WillOnce(Return(response)); expectGetState(1); rule.setEnabled(false); } } TEST_F(RuleTest, getOwner) { const std::string owner = "testowner"; ruleState["owner"] = owner; EXPECT_EQ(owner, getRule().getOwner()); } TEST_F(RuleTest, getConditions) { std::vector conditions = {Condition("/a/b/c", Condition::Operator::eq, "12"), Condition("/d/c", Condition::Operator::dx, "")}; ruleState["conditions"] = {conditions[0].toJson(), conditions[1].toJson()}; const std::vector result = getRule().getConditions(); ASSERT_EQ(2, result.size()); EXPECT_EQ(conditions[0].toJson(), result[0].toJson()); EXPECT_EQ(conditions[1].toJson(), result[1].toJson()); } TEST_F(RuleTest, getActions) { nlohmann::json action0 {{"address", "/a/b"}, {"method", "PUT"}, {"body", {{"value", "test"}}}}; nlohmann::json action1 {{"address", "/c/d"}, {"method", "POST"}, {"body", {{"32", 1}}}}; ruleState["actions"] = {action0, action1}; const std::vector result = getRule().getActions(); ASSERT_EQ(2, result.size()); EXPECT_EQ(action0, result[0].toJson()); EXPECT_EQ(action1, result[1].toJson()); } TEST_F(RuleTest, setConditions) { std::vector conditions = {Condition("/a/b/c", Condition::Operator::eq, "12"), Condition("/d/c", Condition::Operator::dx, "")}; const nlohmann::json request = {{"conditions", {conditions[0].toJson(), conditions[1].toJson()}}}; Rule rule = getRule(); EXPECT_CALL(*handler, PUTJson("/api/" + getBridgeUsername() + "/rules/1", request, getBridgeIp(), getBridgePort())); expectGetState(1); rule.setConditions(conditions); } TEST_F(RuleTest, setActions) { using hueplusplus::Action; nlohmann::json action0 {{"address", "/a/b"}, {"method", "PUT"}, {"body", {{"value", "test"}}}}; nlohmann::json action1 {{"address", "/c/d"}, {"method", "POST"}, {"body", {{"32", 1}}}}; const nlohmann::json request = {{"actions", {action0, action1}}}; const std::vector actions = {Action(action0), Action(action1)}; Rule rule = getRule(); EXPECT_CALL(*handler, PUTJson("/api/" + getBridgeUsername() + "/rules/1", request, getBridgeIp(), getBridgePort())); expectGetState(1); rule.setActions(actions); } TEST(CreateRule, setName) { const std::string name = "New rule"; const nlohmann::json request = {{"conditions", nullptr}, {"actions", nullptr}, {"name", name}}; EXPECT_EQ(request, CreateRule({}, {}).setName(name).getRequest()); } TEST(CreateRule, setStatus) { { const nlohmann::json request = {{"conditions", nullptr}, {"actions", nullptr}, {"status", "enabled"}}; EXPECT_EQ(request, CreateRule({}, {}).setStatus(true).getRequest()); } { const nlohmann::json request = {{"conditions", nullptr}, {"actions", nullptr}, {"status", "disabled"}}; EXPECT_EQ(request, CreateRule({}, {}).setStatus(false).getRequest()); } } TEST(CreateRule, Constructor) { using hueplusplus::Action; std::vector conditions = {Condition("/a/b/c", Condition::Operator::eq, "12"), Condition("/d/c", Condition::Operator::dx, "")}; nlohmann::json action0 {{"address", "/a/b"}, {"method", "PUT"}, {"body", {{"value", "test"}}}}; nlohmann::json action1 {{"address", "/c/d"}, {"method", "POST"}, {"body", {{"32", 1}}}}; const std::vector actions = {Action(action0), Action(action1)}; const nlohmann::json request = {{"conditions", {conditions[0].toJson(), conditions[1].toJson()}}, {"actions", {action0, action1}}}; EXPECT_EQ(request, CreateRule(conditions, actions).getRequest()); }