blob: b035175a824e561c9c6a9be94db8f6d0a370c165 [file] [log] [blame]
Alex Vakulenko07216fe2014-09-19 15:31:09 -07001// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Alex Deymof6cbe322014-11-10 19:55:35 -08005#include "buffet/states/state_manager.h"
6
Alex Vakulenko57123b22014-10-28 13:50:16 -07007#include <cstdlib> // for abs().
8#include <vector>
Alex Vakulenko07216fe2014-09-19 15:31:09 -07009
10#include <base/values.h>
Alex Vakulenko57123b22014-10-28 13:50:16 -070011#include <gmock/gmock.h>
Alex Vakulenko07216fe2014-09-19 15:31:09 -070012#include <gtest/gtest.h>
13
14#include "buffet/commands/schema_constants.h"
15#include "buffet/commands/unittest_utils.h"
16#include "buffet/states/error_codes.h"
Alex Vakulenko57123b22014-10-28 13:50:16 -070017#include "buffet/states/mock_state_change_queue_interface.h"
Alex Vakulenko07216fe2014-09-19 15:31:09 -070018
19using buffet::unittests::CreateDictionaryValue;
20using buffet::unittests::ValueToString;
Alex Vakulenko57123b22014-10-28 13:50:16 -070021using testing::Return;
22using testing::_;
Alex Vakulenko07216fe2014-09-19 15:31:09 -070023
24namespace buffet {
25
26namespace {
27std::unique_ptr<base::DictionaryValue> GetTestSchema() {
28 return CreateDictionaryValue(R"({
29 'base': {
30 'manufacturer':'string',
31 'serialNumber':'string'
32 },
33 'terminator': {
34 'target':'string'
35 }
36 })");
37}
38
39std::unique_ptr<base::DictionaryValue> GetTestValues() {
40 return CreateDictionaryValue(R"({
41 'base': {
42 'manufacturer':'Skynet',
43 'serialNumber':'T1000'
44 }
45 })");
46}
Alex Vakulenko57123b22014-10-28 13:50:16 -070047
Alex Vakulenko07216fe2014-09-19 15:31:09 -070048} // anonymous namespace
49
50class StateManagerTest : public ::testing::Test {
51 public:
52 void SetUp() override {
Alex Vakulenko57123b22014-10-28 13:50:16 -070053 // Initial expectations.
54 EXPECT_CALL(mock_state_change_queue_, IsEmpty()).Times(0);
Alex Vakulenkoff73cf22014-10-29 09:53:52 -070055 EXPECT_CALL(mock_state_change_queue_, NotifyPropertiesUpdated(_, _))
56 .Times(0);
Alex Vakulenko57123b22014-10-28 13:50:16 -070057 EXPECT_CALL(mock_state_change_queue_, GetAndClearRecordedStateChanges())
58 .Times(0);
59 mgr_.reset(new StateManager(&mock_state_change_queue_));
Alex Vakulenko07216fe2014-09-19 15:31:09 -070060 LoadStateDefinition(GetTestSchema().get(), "default", nullptr);
61 ASSERT_TRUE(mgr_->LoadStateDefaults(*GetTestValues().get(), nullptr));
62 }
63 void TearDown() override {
64 mgr_.reset();
65 }
66
67 void LoadStateDefinition(const base::DictionaryValue* json,
68 const std::string& category,
69 chromeos::ErrorPtr* error) {
70 ASSERT_TRUE(mgr_->LoadStateDefinition(*json, category, error));
71 }
72
73 std::unique_ptr<StateManager> mgr_;
Alex Vakulenko57123b22014-10-28 13:50:16 -070074 MockStateChangeQueueInterface mock_state_change_queue_;
Alex Vakulenko07216fe2014-09-19 15:31:09 -070075};
76
77TEST(StateManager, Empty) {
Alex Vakulenko57123b22014-10-28 13:50:16 -070078 MockStateChangeQueueInterface mock_state_change_queue;
79 StateManager manager(&mock_state_change_queue);
Alex Vakulenko07216fe2014-09-19 15:31:09 -070080 EXPECT_TRUE(manager.GetCategories().empty());
81}
82
83TEST_F(StateManagerTest, Initialized) {
84 EXPECT_EQ(std::set<std::string>{"default"}, mgr_->GetCategories());
85 EXPECT_EQ("{'base':{'manufacturer':'Skynet','serialNumber':'T1000'},"
86 "'terminator':{'target':''}}",
87 ValueToString(mgr_->GetStateValuesAsJson(nullptr).get()));
88}
89
90TEST_F(StateManagerTest, LoadStateDefinition) {
91 auto dict = CreateDictionaryValue(R"({
92 'power': {
93 'battery_level':'integer'
94 }
95 })");
96 LoadStateDefinition(dict.get(), "powerd", nullptr);
97 EXPECT_EQ((std::set<std::string>{"default", "powerd"}),
98 mgr_->GetCategories());
99 EXPECT_EQ("{'base':{'manufacturer':'Skynet','serialNumber':'T1000'},"
100 "'power':{'battery_level':0},"
101 "'terminator':{'target':''}}",
102 ValueToString(mgr_->GetStateValuesAsJson(nullptr).get()));
103}
104
105TEST_F(StateManagerTest, SetPropertyValue) {
Anton Muhin01829452014-11-21 02:16:04 +0400106 native_types::Object expected_prop_set{
107 {"terminator.target", unittests::make_string_prop_value("John Connor")},
Alex Vakulenko57123b22014-10-28 13:50:16 -0700108 };
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700109 base::Time timestamp = base::Time::Now();
Alex Vakulenko57123b22014-10-28 13:50:16 -0700110 EXPECT_CALL(mock_state_change_queue_,
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700111 NotifyPropertiesUpdated(timestamp, expected_prop_set))
Alex Vakulenko57123b22014-10-28 13:50:16 -0700112 .WillOnce(Return(true));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700113 ASSERT_TRUE(mgr_->SetPropertyValue("terminator.target",
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700114 std::string{"John Connor"},
115 timestamp,
116 nullptr));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700117 EXPECT_EQ("{'base':{'manufacturer':'Skynet','serialNumber':'T1000'},"
118 "'terminator':{'target':'John Connor'}}",
119 ValueToString(mgr_->GetStateValuesAsJson(nullptr).get()));
120}
121
122TEST_F(StateManagerTest, SetPropertyValue_Error_NoName) {
123 chromeos::ErrorPtr error;
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700124 ASSERT_FALSE(mgr_->SetPropertyValue("", int{0}, base::Time::Now(), &error));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700125 EXPECT_EQ(errors::state::kDomain, error->GetDomain());
126 EXPECT_EQ(errors::state::kPropertyNameMissing, error->GetCode());
127 EXPECT_EQ("Property name is missing", error->GetMessage());
128}
129
130TEST_F(StateManagerTest, SetPropertyValue_Error_NoPackage) {
131 chromeos::ErrorPtr error;
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700132 ASSERT_FALSE(mgr_->SetPropertyValue("target", int{0}, base::Time::Now(),
133 &error));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700134 EXPECT_EQ(errors::state::kDomain, error->GetDomain());
135 EXPECT_EQ(errors::state::kPackageNameMissing, error->GetCode());
136 EXPECT_EQ("Package name is missing in the property name",
137 error->GetMessage());
138}
139
140TEST_F(StateManagerTest, SetPropertyValue_Error_UnknownPackage) {
141 chromeos::ErrorPtr error;
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700142 ASSERT_FALSE(mgr_->SetPropertyValue("power.level", int{0}, base::Time::Now(),
143 &error));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700144 EXPECT_EQ(errors::state::kDomain, error->GetDomain());
145 EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
146 EXPECT_EQ("Unknown state property package 'power'", error->GetMessage());
147}
148
149TEST_F(StateManagerTest, SetPropertyValue_Error_UnknownProperty) {
150 chromeos::ErrorPtr error;
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700151 ASSERT_FALSE(mgr_->SetPropertyValue("base.level", int{0}, base::Time::Now(),
152 &error));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700153 EXPECT_EQ(errors::state::kDomain, error->GetDomain());
154 EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
155 EXPECT_EQ("State property 'base.level' is not defined", error->GetMessage());
156}
157
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700158TEST_F(StateManagerTest, GetAndClearRecordedStateChanges) {
159 base::Time timestamp = base::Time::Now();
160 EXPECT_CALL(mock_state_change_queue_, NotifyPropertiesUpdated(timestamp, _))
Alex Vakulenko57123b22014-10-28 13:50:16 -0700161 .WillOnce(Return(true));
162 ASSERT_TRUE(mgr_->SetPropertyValue("terminator.target",
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700163 std::string{"John Connor"},
164 timestamp,
165 nullptr));
Alex Vakulenko57123b22014-10-28 13:50:16 -0700166 std::vector<StateChange> expected_val;
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700167 expected_val.emplace_back(
168 timestamp,
Anton Muhin01829452014-11-21 02:16:04 +0400169 native_types::Object{{"terminator.target",
170 unittests::make_string_prop_value("John Connor")}});
Alex Vakulenko57123b22014-10-28 13:50:16 -0700171 EXPECT_CALL(mock_state_change_queue_, GetAndClearRecordedStateChanges())
172 .WillOnce(Return(expected_val));
173 auto changes = mgr_->GetAndClearRecordedStateChanges();
174 ASSERT_EQ(1, changes.size());
175 EXPECT_EQ(expected_val.back().timestamp, changes.back().timestamp);
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700176 EXPECT_EQ(expected_val.back().changed_properties,
177 changes.back().changed_properties);
Alex Vakulenko57123b22014-10-28 13:50:16 -0700178}
179
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700180} // namespace buffet