blob: 48d54b9a65491d4ba5aa2710a53630533cdc6f00 [file] [log] [blame]
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -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/commands/command_instance.h"
6
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -07007#include <gtest/gtest.h>
8
Alex Vakulenko8dc69af2014-08-07 10:29:42 -07009#include "buffet/commands/command_dictionary.h"
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070010#include "buffet/commands/prop_types.h"
Anton Muhincfde8692014-11-25 03:36:59 +040011#include "buffet/commands/schema_utils.h"
Alex Vakulenko8dc69af2014-08-07 10:29:42 -070012#include "buffet/commands/unittest_utils.h"
13
14using buffet::unittests::CreateDictionaryValue;
15using buffet::unittests::CreateValue;
16
17namespace {
18
19class CommandInstanceTest : public ::testing::Test {
20 protected:
Alex Vakulenko5a9e7182014-08-11 15:59:58 -070021 void SetUp() override {
Alex Vakulenko8dc69af2014-08-07 10:29:42 -070022 auto json = CreateDictionaryValue(R"({
23 'base': {
24 'reboot': {
Anton Muhin71fb9d52014-11-21 22:22:39 +040025 'parameters': {},
26 'results': {}
Alex Vakulenko8dc69af2014-08-07 10:29:42 -070027 }
28 },
29 'robot': {
30 'jump': {
31 'parameters': {
32 'height': {
33 'type': 'integer',
34 'minimum': 0,
35 'maximum': 100
36 },
37 '_jumpType': {
38 'type': 'string',
39 'enum': ['_withAirFlip', '_withSpin', '_withKick']
40 }
Anton Muhin71fb9d52014-11-21 22:22:39 +040041 },
42 'results': {}
Alex Vakulenko8dc69af2014-08-07 10:29:42 -070043 },
44 'speak': {
45 'parameters': {
46 'phrase': {
47 'type': 'string',
48 'enum': ['beamMeUpScotty', 'iDontDigOnSwine',
49 'iPityDaFool', 'dangerWillRobinson']
50 },
51 'volume': {
52 'type': 'integer',
53 'minimum': 0,
54 'maximum': 10
55 }
Anton Muhin71fb9d52014-11-21 22:22:39 +040056 },
57 'results': {}
Alex Vakulenko8dc69af2014-08-07 10:29:42 -070058 }
59 }
60 })");
61 CHECK(dict_.LoadCommands(*json, "robotd", nullptr, nullptr))
62 << "Failed to parse test command dictionary";
63 }
64 buffet::CommandDictionary dict_;
65};
66
67} // anonymous namespace
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070068
Anton Muhincfde8692014-11-25 03:36:59 +040069TEST_F(CommandInstanceTest, Test) {
70 buffet::StringPropType str_prop;
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070071 buffet::IntPropType int_prop;
Anton Muhincfde8692014-11-25 03:36:59 +040072 buffet::native_types::Object params;
73 params["phrase"] = str_prop.CreateValue(std::string("iPityDaFool"),
74 nullptr);
75 params["volume"] = int_prop.CreateValue(5, nullptr);
76 buffet::CommandInstance instance("robot.speak",
77 dict_.FindCommand("robot.speak"),
78 params);
79
80 buffet::native_types::Object results;
81 results["foo"] = int_prop.CreateValue(239, nullptr);
82 instance.SetResults(results);
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070083
Alex Vakulenkofedc4872014-08-20 12:38:43 -070084 EXPECT_EQ("", instance.GetID());
Anton Muhincfde8692014-11-25 03:36:59 +040085 EXPECT_EQ("robot.speak", instance.GetName());
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070086 EXPECT_EQ("robotd", instance.GetCategory());
87 EXPECT_EQ(params, instance.GetParameters());
Anton Muhincfde8692014-11-25 03:36:59 +040088 EXPECT_EQ("iPityDaFool",
89 instance.FindParameter("phrase")->GetString()->GetValue());
90 EXPECT_EQ(5, instance.FindParameter("volume")->GetInt()->GetValue());
Alex Vakulenko5ef75792015-03-19 15:50:44 -070091 EXPECT_EQ(nullptr, instance.FindParameter("blah"));
Anton Muhincfde8692014-11-25 03:36:59 +040092 EXPECT_EQ(results, instance.GetResults());
Alex Vakulenkoaa3a5592014-08-07 07:24:06 -070093}
Alex Vakulenko8dc69af2014-08-07 10:29:42 -070094
Anton Muhincfde8692014-11-25 03:36:59 +040095TEST_F(CommandInstanceTest, SetID) {
96 buffet::CommandInstance instance("robot._beep",
97 dict_.FindCommand("robot.speak"),
98 {});
Alex Vakulenkofedc4872014-08-20 12:38:43 -070099 instance.SetID("command_id");
100 EXPECT_EQ("command_id", instance.GetID());
101}
102
Alex Vakulenko8dc69af2014-08-07 10:29:42 -0700103TEST_F(CommandInstanceTest, FromJson) {
104 auto json = CreateDictionaryValue(R"({
105 'name': 'robot.jump',
106 'parameters': {
107 'height': 53,
108 '_jumpType': '_withKick'
Anton Muhin71fb9d52014-11-21 22:22:39 +0400109 },
110 'results': {}
Alex Vakulenko8dc69af2014-08-07 10:29:42 -0700111 })");
112 auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, nullptr);
113 EXPECT_EQ("robot.jump", instance->GetName());
114 EXPECT_EQ("robotd", instance->GetCategory());
115 EXPECT_EQ(53, instance->FindParameter("height")->GetInt()->GetValue());
116 EXPECT_EQ("_withKick",
117 instance->FindParameter("_jumpType")->GetString()->GetValue());
118}
119
120TEST_F(CommandInstanceTest, FromJson_ParamsOmitted) {
121 auto json = CreateDictionaryValue("{'name': 'base.reboot'}");
122 auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, nullptr);
123 EXPECT_EQ("base.reboot", instance->GetName());
124 EXPECT_EQ("robotd", instance->GetCategory());
125 EXPECT_TRUE(instance->GetParameters().empty());
126}
127
128TEST_F(CommandInstanceTest, FromJson_NotObject) {
129 auto json = CreateValue("'string'");
Alex Vakulenko5f472062014-08-14 17:54:04 -0700130 chromeos::ErrorPtr error;
Alex Vakulenko8dc69af2014-08-07 10:29:42 -0700131 auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, &error);
132 EXPECT_EQ(nullptr, instance.get());
133 EXPECT_EQ("json_object_expected", error->GetCode());
134 EXPECT_EQ("Command instance is not a JSON object", error->GetMessage());
135}
136
137TEST_F(CommandInstanceTest, FromJson_NameMissing) {
138 auto json = CreateDictionaryValue("{'param': 'value'}");
Alex Vakulenko5f472062014-08-14 17:54:04 -0700139 chromeos::ErrorPtr error;
Alex Vakulenko8dc69af2014-08-07 10:29:42 -0700140 auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, &error);
141 EXPECT_EQ(nullptr, instance.get());
142 EXPECT_EQ("parameter_missing", error->GetCode());
143 EXPECT_EQ("Command name is missing", error->GetMessage());
144}
145
146TEST_F(CommandInstanceTest, FromJson_UnknownCommand) {
147 auto json = CreateDictionaryValue("{'name': 'robot.scream'}");
Alex Vakulenko5f472062014-08-14 17:54:04 -0700148 chromeos::ErrorPtr error;
Alex Vakulenko8dc69af2014-08-07 10:29:42 -0700149 auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, &error);
150 EXPECT_EQ(nullptr, instance.get());
151 EXPECT_EQ("invalid_command_name", error->GetCode());
152 EXPECT_EQ("Unknown command received: robot.scream", error->GetMessage());
153}
154
155TEST_F(CommandInstanceTest, FromJson_ParamsNotObject) {
156 auto json = CreateDictionaryValue(R"({
157 'name': 'robot.speak',
158 'parameters': 'hello'
159 })");
Alex Vakulenko5f472062014-08-14 17:54:04 -0700160 chromeos::ErrorPtr error;
Alex Vakulenko8dc69af2014-08-07 10:29:42 -0700161 auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, &error);
162 EXPECT_EQ(nullptr, instance.get());
163 auto inner = error->GetInnerError();
164 EXPECT_EQ("json_object_expected", inner->GetCode());
165 EXPECT_EQ("Property 'parameters' must be a JSON object", inner->GetMessage());
166 EXPECT_EQ("command_failed", error->GetCode());
167 EXPECT_EQ("Failed to validate command 'robot.speak'", error->GetMessage());
168}
169
170TEST_F(CommandInstanceTest, FromJson_ParamError) {
171 auto json = CreateDictionaryValue(R"({
172 'name': 'robot.speak',
173 'parameters': {
174 'phrase': 'iPityDaFool',
175 'volume': 20
176 }
177 })");
Alex Vakulenko5f472062014-08-14 17:54:04 -0700178 chromeos::ErrorPtr error;
Alex Vakulenko8dc69af2014-08-07 10:29:42 -0700179 auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, &error);
180 EXPECT_EQ(nullptr, instance.get());
181 auto first = error->GetFirstError();
182 EXPECT_EQ("out_of_range", first->GetCode());
183 EXPECT_EQ("Value 20 is out of range. It must not be greater than 10",
184 first->GetMessage());
185 auto inner = error->GetInnerError();
186 EXPECT_EQ("invalid_parameter_value", inner->GetCode());
Alex Vakulenkoa32d83a2014-09-19 15:05:24 -0700187 EXPECT_EQ("Invalid value for property 'volume'",
Alex Vakulenko8dc69af2014-08-07 10:29:42 -0700188 inner->GetMessage());
189 EXPECT_EQ("command_failed", error->GetCode());
190 EXPECT_EQ("Failed to validate command 'robot.speak'", error->GetMessage());
191}
Vitaly Buka906d39e2015-03-24 10:08:26 -0700192
193TEST_F(CommandInstanceTest, ToJson) {
194 auto json = CreateDictionaryValue(R"({
195 'name': 'robot.jump',
196 'parameters': {
197 'height': 53,
198 '_jumpType': '_withKick'
199 },
200 'results': {}
201 })");
202 auto instance = buffet::CommandInstance::FromJson(json.get(), dict_, nullptr);
203 instance->SetProgress(15);
204 instance->SetID("testId");
205 buffet::native_types::Object results;
206 buffet::IntPropType int_prop;
207 results["testResult"] = int_prop.CreateValue(17, nullptr);
208 instance->SetResults(results);
209
210 json->MergeDictionary(CreateDictionaryValue(R"({
211 'id': 'testId',
212 'progress': 15,
213 'state': 'inProgress',
214 'results': {'testResult': 17}
215 })").get());
216
217 auto converted = instance->ToJson();
218 EXPECT_PRED2([](const base::Value& val1, const base::Value& val2) {
219 return val1.Equals(&val2);
220 }, *json, *converted);
221}