blob: d09625af7573403d2ab0a2bc6ce51885b6683a25 [file] [log] [blame]
// Copyright 2015 The Weave Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/states/state_package.h"
#include <memory>
#include <string>
#include <base/values.h>
#include <gtest/gtest.h>
#include <weave/test/unittest_utils.h>
#include "src/commands/schema_constants.h"
#include "src/states/error_codes.h"
namespace weave {
using test::CreateDictionaryValue;
class StatePackageTestHelper {
public:
// Returns the state property definitions (types/constraints/etc).
static const base::DictionaryValue& GetTypes(const StatePackage& package) {
return package.types_;
}
// Returns the all state property values in this package.
static const base::DictionaryValue& GetValues(const StatePackage& package) {
return package.values_;
}
};
namespace {
std::unique_ptr<base::DictionaryValue> GetTestSchema() {
return CreateDictionaryValue(R"({
'color': {
'type': 'string'
},
'direction': {
'additionalProperties': false,
'properties': {
'altitude': {
'maximum': 90.0,
'type': 'number'
},
'azimuth': {
'type': 'number'
}
},
'type': 'object',
'required': [ 'azimuth' ]
},
'iso': {
'enum': [50, 100, 200, 400],
'type': 'integer'
},
'light': {
'type': 'boolean'
}
})");
}
std::unique_ptr<base::DictionaryValue> GetTestValues() {
return CreateDictionaryValue(R"({
'light': true,
'color': 'white',
'direction': {'azimuth':57.2957795, 'altitude':89.9},
'iso': 200
})");
}
inline const base::DictionaryValue& GetTypes(const StatePackage& package) {
return StatePackageTestHelper::GetTypes(package);
}
// Returns the all state property values in this package.
inline const base::DictionaryValue& GetValues(const StatePackage& package) {
return StatePackageTestHelper::GetValues(package);
}
} // anonymous namespace
class StatePackageTest : public ::testing::Test {
public:
void SetUp() override {
package_.reset(new StatePackage("test"));
ASSERT_TRUE(package_->AddSchemaFromJson(GetTestSchema().get(), nullptr));
ASSERT_TRUE(package_->AddValuesFromJson(GetTestValues().get(), nullptr));
}
void TearDown() override { package_.reset(); }
std::unique_ptr<StatePackage> package_;
};
TEST(StatePackage, Empty) {
StatePackage package("test");
EXPECT_EQ("test", package.GetName());
EXPECT_TRUE(GetTypes(package).empty());
EXPECT_TRUE(GetValues(package).empty());
}
TEST(StatePackage, AddSchemaFromJson_OnEmpty) {
StatePackage package("test");
ASSERT_TRUE(package.AddSchemaFromJson(GetTestSchema().get(), nullptr));
EXPECT_EQ(4u, GetTypes(package).size());
EXPECT_EQ(0u, GetValues(package).size());
auto expected = R"({
'color': {
'type': 'string'
},
'direction': {
'additionalProperties': false,
'properties': {
'altitude': {
'maximum': 90.0,
'type': 'number'
},
'azimuth': {
'type': 'number'
}
},
'type': 'object',
'required': [ 'azimuth' ]
},
'iso': {
'enum': [50, 100, 200, 400],
'type': 'integer'
},
'light': {
'type': 'boolean'
}
})";
EXPECT_JSON_EQ(expected, GetTypes(package));
EXPECT_JSON_EQ("{}", package.GetValuesAsJson());
}
TEST(StatePackage, AddValuesFromJson_OnEmpty) {
StatePackage package("test");
ASSERT_TRUE(package.AddSchemaFromJson(GetTestSchema().get(), nullptr));
ASSERT_TRUE(package.AddValuesFromJson(GetTestValues().get(), nullptr));
EXPECT_EQ(4u, GetValues(package).size());
auto expected = R"({
'color': 'white',
'direction': {
'altitude': 89.9,
'azimuth': 57.2957795
},
'iso': 200,
'light': true
})";
EXPECT_JSON_EQ(expected, package.GetValuesAsJson());
}
TEST_F(StatePackageTest, AddSchemaFromJson_AddMore) {
auto dict = CreateDictionaryValue(R"({'brightness':{
'enum': ['low', 'medium', 'high'],
'type': 'string'
}})");
ASSERT_TRUE(package_->AddSchemaFromJson(dict.get(), nullptr));
EXPECT_EQ(5u, GetTypes(*package_).size());
EXPECT_EQ(4u, GetValues(*package_).size());
auto expected = R"({
'brightness': {
'enum': ['low', 'medium', 'high'],
'type': 'string'
},
'color': {
'type': 'string'
},
'direction': {
'additionalProperties': false,
'properties': {
'altitude': {
'maximum': 90.0,
'type': 'number'
},
'azimuth': {
'type': 'number'
}
},
'type': 'object',
'required': [ 'azimuth' ]
},
'iso': {
'enum': [50, 100, 200, 400],
'type': 'integer'
},
'light': {
'type': 'boolean'
}
})";
EXPECT_JSON_EQ(expected, GetTypes(*package_));
expected = R"({
'color': 'white',
'direction': {
'altitude': 89.9,
'azimuth': 57.2957795
},
'iso': 200,
'light': true
})";
EXPECT_JSON_EQ(expected, package_->GetValuesAsJson());
}
TEST_F(StatePackageTest, AddValuesFromJson_AddMore) {
auto dict = CreateDictionaryValue(R"({'brightness':{
'enum': ['low', 'medium', 'high'],
'type': 'string'
}})");
ASSERT_TRUE(package_->AddSchemaFromJson(dict.get(), nullptr));
dict = CreateDictionaryValue("{'brightness':'medium'}");
ASSERT_TRUE(package_->AddValuesFromJson(dict.get(), nullptr));
EXPECT_EQ(5u, GetValues(*package_).size());
auto expected = R"({
'brightness': 'medium',
'color': 'white',
'direction': {
'altitude': 89.9,
'azimuth': 57.2957795
},
'iso': 200,
'light': true
})";
EXPECT_JSON_EQ(expected, package_->GetValuesAsJson());
}
TEST_F(StatePackageTest, AddSchemaFromJson_Error_Redefined) {
auto dict = CreateDictionaryValue(R"({'color':
{'type':'string', 'enum':['white', 'blue', 'red']}})");
ErrorPtr error;
EXPECT_FALSE(package_->AddSchemaFromJson(dict.get(), &error));
EXPECT_EQ(errors::state::kDomain, error->GetDomain());
EXPECT_EQ(errors::state::kPropertyRedefinition, error->GetCode());
}
TEST_F(StatePackageTest, AddValuesFromJson_Error_Undefined) {
auto dict = CreateDictionaryValue("{'brightness':'medium'}");
EXPECT_TRUE(package_->AddValuesFromJson(dict.get(), nullptr));
}
TEST_F(StatePackageTest, GetPropertyValue) {
EXPECT_JSON_EQ("'white'", *package_->GetPropertyValue("color", nullptr));
EXPECT_JSON_EQ("true", *package_->GetPropertyValue("light", nullptr));
EXPECT_JSON_EQ("200", *package_->GetPropertyValue("iso", nullptr));
EXPECT_JSON_EQ("{'altitude': 89.9, 'azimuth': 57.2957795}",
*package_->GetPropertyValue("direction", nullptr));
}
TEST_F(StatePackageTest, GetPropertyValue_Unknown) {
ErrorPtr error;
EXPECT_EQ(nullptr, package_->GetPropertyValue("volume", &error));
EXPECT_EQ(errors::state::kDomain, error->GetDomain());
EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
}
TEST_F(StatePackageTest, SetPropertyValue_Simple) {
EXPECT_TRUE(
package_->SetPropertyValue("color", base::StringValue{"blue"}, nullptr));
EXPECT_JSON_EQ("'blue'", *package_->GetPropertyValue("color", nullptr));
EXPECT_TRUE(package_->SetPropertyValue("light", base::FundamentalValue{false},
nullptr));
bool light = false;
ASSERT_TRUE(
package_->GetPropertyValue("light", nullptr)->GetAsBoolean(&light));
EXPECT_FALSE(light);
EXPECT_TRUE(
package_->SetPropertyValue("iso", base::FundamentalValue{400}, nullptr));
EXPECT_JSON_EQ("400", *package_->GetPropertyValue("iso", nullptr));
}
TEST_F(StatePackageTest, SetPropertyValue_Object) {
EXPECT_TRUE(package_->SetPropertyValue(
"direction",
*CreateDictionaryValue("{'altitude': 45.0, 'azimuth': 15.0}"), nullptr));
auto expected = R"({
'color': 'white',
'direction': {
'altitude': 45.0,
'azimuth': 15.0
},
'iso': 200,
'light': true
})";
EXPECT_JSON_EQ(expected, package_->GetValuesAsJson());
}
} // namespace weave