blob: 50e6a5f5e08dd3ec06364d14d5f3f59221f3e041 [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
Vitaly Buka247620b2015-05-26 15:42:20 -070010#include <base/bind.h>
Alex Vakulenko07216fe2014-09-19 15:31:09 -070011#include <base/values.h>
Alex Vakulenko57123b22014-10-28 13:50:16 -070012#include <gmock/gmock.h>
Alex Vakulenko07216fe2014-09-19 15:31:09 -070013#include <gtest/gtest.h>
14
15#include "buffet/commands/schema_constants.h"
16#include "buffet/commands/unittest_utils.h"
17#include "buffet/states/error_codes.h"
Alex Vakulenko57123b22014-10-28 13:50:16 -070018#include "buffet/states/mock_state_change_queue_interface.h"
Alex Vakulenko07216fe2014-09-19 15:31:09 -070019
Alex Vakulenko07216fe2014-09-19 15:31:09 -070020namespace buffet {
21
Vitaly Buka32005de2015-05-01 12:33:31 -070022using testing::_;
23using testing::Return;
24using unittests::CreateDictionaryValue;
Vitaly Buka32005de2015-05-01 12:33:31 -070025
Alex Vakulenko07216fe2014-09-19 15:31:09 -070026namespace {
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(_, _))
Vitaly Buka7c82d292015-05-03 18:08:12 -070056 .Times(0);
Alex Vakulenko57123b22014-10-28 13:50:16 -070057 EXPECT_CALL(mock_state_change_queue_, GetAndClearRecordedStateChanges())
Vitaly Buka7c82d292015-05-03 18:08:12 -070058 .Times(0);
Alex Vakulenko57123b22014-10-28 13:50:16 -070059 mgr_.reset(new StateManager(&mock_state_change_queue_));
Vitaly Buka247620b2015-05-26 15:42:20 -070060
61 EXPECT_CALL(*this, OnStateChanged()).Times(1);
62 mgr_->AddOnChangedCallback(
63 base::Bind(&StateManagerTest::OnStateChanged, base::Unretained(this)));
64
Alex Vakulenko07216fe2014-09-19 15:31:09 -070065 LoadStateDefinition(GetTestSchema().get(), "default", nullptr);
66 ASSERT_TRUE(mgr_->LoadStateDefaults(*GetTestValues().get(), nullptr));
67 }
Vitaly Buka7c82d292015-05-03 18:08:12 -070068 void TearDown() override { mgr_.reset(); }
Alex Vakulenko07216fe2014-09-19 15:31:09 -070069
70 void LoadStateDefinition(const base::DictionaryValue* json,
71 const std::string& category,
72 chromeos::ErrorPtr* error) {
73 ASSERT_TRUE(mgr_->LoadStateDefinition(*json, category, error));
74 }
75
Vitaly Buka247620b2015-05-26 15:42:20 -070076 bool SetPropertyValue(const std::string& name,
77 const chromeos::Any& value,
78 chromeos::ErrorPtr* error) {
79 return mgr_->SetPropertyValue(name, value, timestamp_, error);
80 }
81
82 MOCK_CONST_METHOD0(OnStateChanged, void());
83
84 base::Time timestamp_{base::Time::Now()};
Alex Vakulenko07216fe2014-09-19 15:31:09 -070085 std::unique_ptr<StateManager> mgr_;
Alex Vakulenko57123b22014-10-28 13:50:16 -070086 MockStateChangeQueueInterface mock_state_change_queue_;
Alex Vakulenko07216fe2014-09-19 15:31:09 -070087};
88
89TEST(StateManager, Empty) {
Alex Vakulenko57123b22014-10-28 13:50:16 -070090 MockStateChangeQueueInterface mock_state_change_queue;
91 StateManager manager(&mock_state_change_queue);
Alex Vakulenko07216fe2014-09-19 15:31:09 -070092 EXPECT_TRUE(manager.GetCategories().empty());
93}
94
95TEST_F(StateManagerTest, Initialized) {
96 EXPECT_EQ(std::set<std::string>{"default"}, mgr_->GetCategories());
Vitaly Buka7c82d292015-05-03 18:08:12 -070097 auto expected = R"({
98 'base': {
99 'manufacturer': 'Skynet',
100 'serialNumber': 'T1000'
101 },
102 'terminator': {
103 'target': ''
104 }
105 })";
106 EXPECT_JSON_EQ(expected, *mgr_->GetStateValuesAsJson(nullptr));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700107}
108
109TEST_F(StateManagerTest, LoadStateDefinition) {
110 auto dict = CreateDictionaryValue(R"({
111 'power': {
112 'battery_level':'integer'
113 }
114 })");
115 LoadStateDefinition(dict.get(), "powerd", nullptr);
116 EXPECT_EQ((std::set<std::string>{"default", "powerd"}),
117 mgr_->GetCategories());
Vitaly Buka7c82d292015-05-03 18:08:12 -0700118
119 auto expected = R"({
120 'base': {
121 'manufacturer': 'Skynet',
122 'serialNumber': 'T1000'
123 },
124 'power': {
125 'battery_level': 0
126 },
127 'terminator': {
128 'target': ''
129 }
130 })";
131 EXPECT_JSON_EQ(expected, *mgr_->GetStateValuesAsJson(nullptr));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700132}
133
134TEST_F(StateManagerTest, SetPropertyValue) {
Anton Muhin01829452014-11-21 02:16:04 +0400135 native_types::Object expected_prop_set{
Vitaly Buka7c82d292015-05-03 18:08:12 -0700136 {"terminator.target", unittests::make_string_prop_value("John Connor")},
Alex Vakulenko57123b22014-10-28 13:50:16 -0700137 };
138 EXPECT_CALL(mock_state_change_queue_,
Vitaly Buka247620b2015-05-26 15:42:20 -0700139 NotifyPropertiesUpdated(timestamp_, expected_prop_set))
Alex Vakulenko57123b22014-10-28 13:50:16 -0700140 .WillOnce(Return(true));
Vitaly Buka247620b2015-05-26 15:42:20 -0700141 ASSERT_TRUE(SetPropertyValue("terminator.target", std::string{"John Connor"},
142 nullptr));
Vitaly Buka7c82d292015-05-03 18:08:12 -0700143 auto expected = R"({
144 'base': {
145 'manufacturer': 'Skynet',
146 'serialNumber': 'T1000'
147 },
148 'terminator': {
149 'target': 'John Connor'
150 }
151 })";
152 EXPECT_JSON_EQ(expected, *mgr_->GetStateValuesAsJson(nullptr));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700153}
154
155TEST_F(StateManagerTest, SetPropertyValue_Error_NoName) {
156 chromeos::ErrorPtr error;
Vitaly Buka247620b2015-05-26 15:42:20 -0700157 ASSERT_FALSE(SetPropertyValue("", int{0}, &error));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700158 EXPECT_EQ(errors::state::kDomain, error->GetDomain());
159 EXPECT_EQ(errors::state::kPropertyNameMissing, error->GetCode());
160 EXPECT_EQ("Property name is missing", error->GetMessage());
161}
162
163TEST_F(StateManagerTest, SetPropertyValue_Error_NoPackage) {
164 chromeos::ErrorPtr error;
Vitaly Buka247620b2015-05-26 15:42:20 -0700165 ASSERT_FALSE(SetPropertyValue("target", int{0}, &error));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700166 EXPECT_EQ(errors::state::kDomain, error->GetDomain());
167 EXPECT_EQ(errors::state::kPackageNameMissing, error->GetCode());
168 EXPECT_EQ("Package name is missing in the property name",
169 error->GetMessage());
170}
171
172TEST_F(StateManagerTest, SetPropertyValue_Error_UnknownPackage) {
173 chromeos::ErrorPtr error;
Vitaly Buka247620b2015-05-26 15:42:20 -0700174 ASSERT_FALSE(SetPropertyValue("power.level", int{0}, &error));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700175 EXPECT_EQ(errors::state::kDomain, error->GetDomain());
176 EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
177 EXPECT_EQ("Unknown state property package 'power'", error->GetMessage());
178}
179
180TEST_F(StateManagerTest, SetPropertyValue_Error_UnknownProperty) {
181 chromeos::ErrorPtr error;
Vitaly Buka247620b2015-05-26 15:42:20 -0700182 ASSERT_FALSE(SetPropertyValue("base.level", int{0}, &error));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700183 EXPECT_EQ(errors::state::kDomain, error->GetDomain());
184 EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
185 EXPECT_EQ("State property 'base.level' is not defined", error->GetMessage());
186}
187
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700188TEST_F(StateManagerTest, GetAndClearRecordedStateChanges) {
Vitaly Buka247620b2015-05-26 15:42:20 -0700189 EXPECT_CALL(mock_state_change_queue_, NotifyPropertiesUpdated(timestamp_, _))
Alex Vakulenko57123b22014-10-28 13:50:16 -0700190 .WillOnce(Return(true));
Vitaly Buka247620b2015-05-26 15:42:20 -0700191 ASSERT_TRUE(SetPropertyValue("terminator.target", std::string{"John Connor"},
192 nullptr));
Alex Vakulenko57123b22014-10-28 13:50:16 -0700193 std::vector<StateChange> expected_val;
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700194 expected_val.emplace_back(
Vitaly Buka247620b2015-05-26 15:42:20 -0700195 timestamp_,
Anton Muhin01829452014-11-21 02:16:04 +0400196 native_types::Object{{"terminator.target",
197 unittests::make_string_prop_value("John Connor")}});
Alex Vakulenko57123b22014-10-28 13:50:16 -0700198 EXPECT_CALL(mock_state_change_queue_, GetAndClearRecordedStateChanges())
199 .WillOnce(Return(expected_val));
200 auto changes = mgr_->GetAndClearRecordedStateChanges();
201 ASSERT_EQ(1, changes.size());
202 EXPECT_EQ(expected_val.back().timestamp, changes.back().timestamp);
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700203 EXPECT_EQ(expected_val.back().changed_properties,
204 changes.back().changed_properties);
Alex Vakulenko57123b22014-10-28 13:50:16 -0700205}
206
Vitaly Buka247620b2015-05-26 15:42:20 -0700207TEST_F(StateManagerTest, SetProperties) {
208 native_types::Object expected_prop_set{
209 {"base.manufacturer", unittests::make_string_prop_value("No Name")},
210 };
211 EXPECT_CALL(mock_state_change_queue_,
212 NotifyPropertiesUpdated(_, expected_prop_set))
213 .WillOnce(Return(true));
214
215 EXPECT_CALL(*this, OnStateChanged()).Times(1);
216 ASSERT_TRUE(mgr_->SetProperties(
217 {{"base.manufacturer", std::string("No Name")}}, nullptr));
218
219 auto expected = R"({
220 'base': {
221 'manufacturer': 'No Name',
222 'serialNumber': 'T1000'
223 },
224 'terminator': {
225 'target': ''
226 }
227 })";
228 EXPECT_JSON_EQ(expected, *mgr_->GetStateValuesAsJson(nullptr));
229}
230
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700231} // namespace buffet