blob: d71ebb618373bedae72b162d1254c01c83996cd8 [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
Alex Vakulenko07216fe2014-09-19 15:31:09 -070019namespace buffet {
20
Vitaly Buka32005de2015-05-01 12:33:31 -070021using testing::_;
22using testing::Return;
23using unittests::CreateDictionaryValue;
Vitaly Buka32005de2015-05-01 12:33:31 -070024
Alex Vakulenko07216fe2014-09-19 15:31:09 -070025namespace {
26std::unique_ptr<base::DictionaryValue> GetTestSchema() {
27 return CreateDictionaryValue(R"({
28 'base': {
29 'manufacturer':'string',
30 'serialNumber':'string'
31 },
32 'terminator': {
33 'target':'string'
34 }
35 })");
36}
37
38std::unique_ptr<base::DictionaryValue> GetTestValues() {
39 return CreateDictionaryValue(R"({
40 'base': {
41 'manufacturer':'Skynet',
42 'serialNumber':'T1000'
43 }
44 })");
45}
Alex Vakulenko57123b22014-10-28 13:50:16 -070046
Alex Vakulenko07216fe2014-09-19 15:31:09 -070047} // anonymous namespace
48
49class StateManagerTest : public ::testing::Test {
50 public:
51 void SetUp() override {
Alex Vakulenko57123b22014-10-28 13:50:16 -070052 // Initial expectations.
53 EXPECT_CALL(mock_state_change_queue_, IsEmpty()).Times(0);
Alex Vakulenkoff73cf22014-10-29 09:53:52 -070054 EXPECT_CALL(mock_state_change_queue_, NotifyPropertiesUpdated(_, _))
Vitaly Buka7c82d292015-05-03 18:08:12 -070055 .Times(0);
Alex Vakulenko57123b22014-10-28 13:50:16 -070056 EXPECT_CALL(mock_state_change_queue_, GetAndClearRecordedStateChanges())
Vitaly Buka7c82d292015-05-03 18:08:12 -070057 .Times(0);
Alex Vakulenko57123b22014-10-28 13:50:16 -070058 mgr_.reset(new StateManager(&mock_state_change_queue_));
Alex Vakulenko07216fe2014-09-19 15:31:09 -070059 LoadStateDefinition(GetTestSchema().get(), "default", nullptr);
60 ASSERT_TRUE(mgr_->LoadStateDefaults(*GetTestValues().get(), nullptr));
61 }
Vitaly Buka7c82d292015-05-03 18:08:12 -070062 void TearDown() override { mgr_.reset(); }
Alex Vakulenko07216fe2014-09-19 15:31:09 -070063
64 void LoadStateDefinition(const base::DictionaryValue* json,
65 const std::string& category,
66 chromeos::ErrorPtr* error) {
67 ASSERT_TRUE(mgr_->LoadStateDefinition(*json, category, error));
68 }
69
70 std::unique_ptr<StateManager> mgr_;
Alex Vakulenko57123b22014-10-28 13:50:16 -070071 MockStateChangeQueueInterface mock_state_change_queue_;
Alex Vakulenko07216fe2014-09-19 15:31:09 -070072};
73
74TEST(StateManager, Empty) {
Alex Vakulenko57123b22014-10-28 13:50:16 -070075 MockStateChangeQueueInterface mock_state_change_queue;
76 StateManager manager(&mock_state_change_queue);
Alex Vakulenko07216fe2014-09-19 15:31:09 -070077 EXPECT_TRUE(manager.GetCategories().empty());
78}
79
80TEST_F(StateManagerTest, Initialized) {
81 EXPECT_EQ(std::set<std::string>{"default"}, mgr_->GetCategories());
Vitaly Buka7c82d292015-05-03 18:08:12 -070082 auto expected = R"({
83 'base': {
84 'manufacturer': 'Skynet',
85 'serialNumber': 'T1000'
86 },
87 'terminator': {
88 'target': ''
89 }
90 })";
91 EXPECT_JSON_EQ(expected, *mgr_->GetStateValuesAsJson(nullptr));
Alex Vakulenko07216fe2014-09-19 15:31:09 -070092}
93
94TEST_F(StateManagerTest, LoadStateDefinition) {
95 auto dict = CreateDictionaryValue(R"({
96 'power': {
97 'battery_level':'integer'
98 }
99 })");
100 LoadStateDefinition(dict.get(), "powerd", nullptr);
101 EXPECT_EQ((std::set<std::string>{"default", "powerd"}),
102 mgr_->GetCategories());
Vitaly Buka7c82d292015-05-03 18:08:12 -0700103
104 auto expected = R"({
105 'base': {
106 'manufacturer': 'Skynet',
107 'serialNumber': 'T1000'
108 },
109 'power': {
110 'battery_level': 0
111 },
112 'terminator': {
113 'target': ''
114 }
115 })";
116 EXPECT_JSON_EQ(expected, *mgr_->GetStateValuesAsJson(nullptr));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700117}
118
119TEST_F(StateManagerTest, SetPropertyValue) {
Anton Muhin01829452014-11-21 02:16:04 +0400120 native_types::Object expected_prop_set{
Vitaly Buka7c82d292015-05-03 18:08:12 -0700121 {"terminator.target", unittests::make_string_prop_value("John Connor")},
Alex Vakulenko57123b22014-10-28 13:50:16 -0700122 };
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700123 base::Time timestamp = base::Time::Now();
Alex Vakulenko57123b22014-10-28 13:50:16 -0700124 EXPECT_CALL(mock_state_change_queue_,
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700125 NotifyPropertiesUpdated(timestamp, expected_prop_set))
Alex Vakulenko57123b22014-10-28 13:50:16 -0700126 .WillOnce(Return(true));
Vitaly Buka7c82d292015-05-03 18:08:12 -0700127 ASSERT_TRUE(mgr_->SetPropertyValue(
128 "terminator.target", std::string{"John Connor"}, timestamp, nullptr));
129 auto expected = R"({
130 'base': {
131 'manufacturer': 'Skynet',
132 'serialNumber': 'T1000'
133 },
134 'terminator': {
135 'target': 'John Connor'
136 }
137 })";
138 EXPECT_JSON_EQ(expected, *mgr_->GetStateValuesAsJson(nullptr));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700139}
140
141TEST_F(StateManagerTest, SetPropertyValue_Error_NoName) {
142 chromeos::ErrorPtr error;
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700143 ASSERT_FALSE(mgr_->SetPropertyValue("", int{0}, base::Time::Now(), &error));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700144 EXPECT_EQ(errors::state::kDomain, error->GetDomain());
145 EXPECT_EQ(errors::state::kPropertyNameMissing, error->GetCode());
146 EXPECT_EQ("Property name is missing", error->GetMessage());
147}
148
149TEST_F(StateManagerTest, SetPropertyValue_Error_NoPackage) {
150 chromeos::ErrorPtr error;
Vitaly Buka7c82d292015-05-03 18:08:12 -0700151 ASSERT_FALSE(
152 mgr_->SetPropertyValue("target", int{0}, base::Time::Now(), &error));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700153 EXPECT_EQ(errors::state::kDomain, error->GetDomain());
154 EXPECT_EQ(errors::state::kPackageNameMissing, error->GetCode());
155 EXPECT_EQ("Package name is missing in the property name",
156 error->GetMessage());
157}
158
159TEST_F(StateManagerTest, SetPropertyValue_Error_UnknownPackage) {
160 chromeos::ErrorPtr error;
Vitaly Buka7c82d292015-05-03 18:08:12 -0700161 ASSERT_FALSE(
162 mgr_->SetPropertyValue("power.level", int{0}, base::Time::Now(), &error));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700163 EXPECT_EQ(errors::state::kDomain, error->GetDomain());
164 EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
165 EXPECT_EQ("Unknown state property package 'power'", error->GetMessage());
166}
167
168TEST_F(StateManagerTest, SetPropertyValue_Error_UnknownProperty) {
169 chromeos::ErrorPtr error;
Vitaly Buka7c82d292015-05-03 18:08:12 -0700170 ASSERT_FALSE(
171 mgr_->SetPropertyValue("base.level", int{0}, base::Time::Now(), &error));
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700172 EXPECT_EQ(errors::state::kDomain, error->GetDomain());
173 EXPECT_EQ(errors::state::kPropertyNotDefined, error->GetCode());
174 EXPECT_EQ("State property 'base.level' is not defined", error->GetMessage());
175}
176
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700177TEST_F(StateManagerTest, GetAndClearRecordedStateChanges) {
178 base::Time timestamp = base::Time::Now();
179 EXPECT_CALL(mock_state_change_queue_, NotifyPropertiesUpdated(timestamp, _))
Alex Vakulenko57123b22014-10-28 13:50:16 -0700180 .WillOnce(Return(true));
Vitaly Buka7c82d292015-05-03 18:08:12 -0700181 ASSERT_TRUE(mgr_->SetPropertyValue(
182 "terminator.target", std::string{"John Connor"}, timestamp, nullptr));
Alex Vakulenko57123b22014-10-28 13:50:16 -0700183 std::vector<StateChange> expected_val;
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700184 expected_val.emplace_back(
185 timestamp,
Anton Muhin01829452014-11-21 02:16:04 +0400186 native_types::Object{{"terminator.target",
187 unittests::make_string_prop_value("John Connor")}});
Alex Vakulenko57123b22014-10-28 13:50:16 -0700188 EXPECT_CALL(mock_state_change_queue_, GetAndClearRecordedStateChanges())
189 .WillOnce(Return(expected_val));
190 auto changes = mgr_->GetAndClearRecordedStateChanges();
191 ASSERT_EQ(1, changes.size());
192 EXPECT_EQ(expected_val.back().timestamp, changes.back().timestamp);
Alex Vakulenkoff73cf22014-10-29 09:53:52 -0700193 EXPECT_EQ(expected_val.back().changed_properties,
194 changes.back().changed_properties);
Alex Vakulenko57123b22014-10-28 13:50:16 -0700195}
196
Alex Vakulenko07216fe2014-09-19 15:31:09 -0700197} // namespace buffet