blob: b035175a824e561c9c6a9be94db8f6d0a370c165 [file] [log] [blame]
// Copyright 2014 The Chromium OS 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 "buffet/states/state_manager.h"
#include <cstdlib> // for abs().
#include <vector>
#include <base/values.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "buffet/commands/schema_constants.h"
#include "buffet/commands/unittest_utils.h"
#include "buffet/states/error_codes.h"
#include "buffet/states/mock_state_change_queue_interface.h"
using buffet::unittests::CreateDictionaryValue;
using buffet::unittests::ValueToString;
using testing::Return;
using testing::_;
namespace buffet {
namespace {
std::unique_ptr<base::DictionaryValue> GetTestSchema() {
return CreateDictionaryValue(R"({
'base': {
'manufacturer':'string',
'serialNumber':'string'
},
'terminator': {
'target':'string'
}
})");
}
std::unique_ptr<base::DictionaryValue> GetTestValues() {
return CreateDictionaryValue(R"({
'base': {
'manufacturer':'Skynet',
'serialNumber':'T1000'
}
})");
}
} // anonymous namespace
class StateManagerTest : public ::testing::Test {
public:
void SetUp() override {
// Initial expectations.
EXPECT_CALL(mock_state_change_queue_, IsEmpty()).Times(0);
EXPECT_CALL(mock_state_change_queue_, NotifyPropertiesUpdated(_, _))
.Times(0);
EXPECT_CALL(mock_state_change_queue_, GetAndClearRecordedStateChanges())
.Times(0);
mgr_.reset(new StateManager(&mock_state_change_queue_));
LoadStateDefinition(GetTestSchema().get(), "default", nullptr);
ASSERT_TRUE(mgr_->LoadStateDefaults(*GetTestValues().get(), nullptr));
}
void TearDown() override {
mgr_.reset();
}
void LoadStateDefinition(const base::DictionaryValue* json,
const std::string& category,
chromeos::ErrorPtr* error) {
ASSERT_TRUE(mgr_->LoadStateDefinition(*json, category, error));
}
std::unique_ptr<StateManager> mgr_;
MockStateChangeQueueInterface mock_state_change_queue_;
};
TEST(StateManager, Empty) {
MockStateChangeQueueInterface mock_state_change_queue;
StateManager manager(&mock_state_change_queue);
EXPECT_TRUE(manager.GetCategories().empty());
}
TEST_F(StateManagerTest, Initialized) {
EXPECT_EQ(std::set<std::string>{"default"}, mgr_->GetCategories());
EXPECT_EQ("{'base':{'manufacturer':'Skynet','serialNumber':'T1000'},"
"'terminator':{'target':''}}",
ValueToString(mgr_->GetStateValuesAsJson(nullptr).get()));
}
TEST_F(StateManagerTest, LoadStateDefinition) {
auto dict = CreateDictionaryValue(R"({
'power': {
'battery_level':'integer'
}
})");
LoadStateDefinition(dict.get(), "powerd", nullptr);
EXPECT_EQ((std::set<std::string>{"default", "powerd"}),
mgr_->GetCategories());
EXPECT_EQ("{'base':{'manufacturer':'Skynet','serialNumber':'T1000'},"
"'power':{'battery_level':0},"
"'terminator':{'target':''}}",
ValueToString(mgr_->GetStateValuesAsJson(nullptr).get()));
}
TEST_F(StateManagerTest, SetPropertyValue) {
native_types::Object expected_prop_set{
{"terminator.target", unittests::make_string_prop_value("John Connor")},
};
base::Time timestamp = base::Time::Now();
EXPECT_CALL(mock_state_change_queue_,
NotifyPropertiesUpdated(timestamp, expected_prop_set))
.WillOnce(Return(true));
ASSERT_TRUE(mgr_->SetPropertyValue("terminator.target",
std::string{"John Connor"},
timestamp,
nullptr));
EXPECT_EQ("{'base':{'manufacturer':'Skynet','serialNumber':'T1000'},"
"'terminator':{'target':'John Connor'}}",
ValueToString(mgr_->GetStateValuesAsJson(nullptr).get()));
}
TEST_F(StateManagerTest, SetPropertyValue_Error_NoName) {
chromeos::ErrorPtr error;
ASSERT_FALSE(mgr_->SetPropertyValue("", int{0}, base::Time::Now(), &error));
EXPECT_EQ(errors::state::kDomain, error->GetDomain());
EXPECT_EQ(errors::state::kPropertyNameMissing, error->GetCode());
EXPECT_EQ("Property name is missing", error->GetMessage());
}
TEST_F(StateManagerTest, SetPropertyValue_Error_NoPackage) {
chromeos::ErrorPtr error;
ASSERT_FALSE(mgr_->SetPropertyValue("target", int{0}, base::Time::Now(),
&error));
EXPECT_EQ(errors::state::kDomain, error->GetDomain());
EXPECT_EQ(errors::state::kPackageNameMissing, error->GetCode());
EXPECT_EQ("Package name is missing in the property name",
error->GetMessage());
}
TEST_F(StateManagerTest, SetPropertyValue_Error_UnknownPackage) {
chromeos::ErrorPtr error;
ASSERT_FALSE(mgr_->SetPropertyValue("power.level", int{0}, base::Time::Now(),
&error));
EXPECT_EQ(errors::state::kDomain, error->GetDomain());
EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
EXPECT_EQ("Unknown state property package 'power'", error->GetMessage());
}
TEST_F(StateManagerTest, SetPropertyValue_Error_UnknownProperty) {
chromeos::ErrorPtr error;
ASSERT_FALSE(mgr_->SetPropertyValue("base.level", int{0}, base::Time::Now(),
&error));
EXPECT_EQ(errors::state::kDomain, error->GetDomain());
EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
EXPECT_EQ("State property 'base.level' is not defined", error->GetMessage());
}
TEST_F(StateManagerTest, GetAndClearRecordedStateChanges) {
base::Time timestamp = base::Time::Now();
EXPECT_CALL(mock_state_change_queue_, NotifyPropertiesUpdated(timestamp, _))
.WillOnce(Return(true));
ASSERT_TRUE(mgr_->SetPropertyValue("terminator.target",
std::string{"John Connor"},
timestamp,
nullptr));
std::vector<StateChange> expected_val;
expected_val.emplace_back(
timestamp,
native_types::Object{{"terminator.target",
unittests::make_string_prop_value("John Connor")}});
EXPECT_CALL(mock_state_change_queue_, GetAndClearRecordedStateChanges())
.WillOnce(Return(expected_val));
auto changes = mgr_->GetAndClearRecordedStateChanges();
ASSERT_EQ(1, changes.size());
EXPECT_EQ(expected_val.back().timestamp, changes.back().timestamp);
EXPECT_EQ(expected_val.back().changed_properties,
changes.back().changed_properties);
}
} // namespace buffet