blob: 865ba6e410af3b6a81f6f971ad18f2f3469309d8 [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 "src/commands/command_instance.h"
#include <gtest/gtest.h>
#include "src/commands/command_dictionary.h"
#include "src/commands/prop_types.h"
#include "src/commands/schema_utils.h"
#include "src/commands/unittest_utils.h"
namespace weave {
using test::CreateDictionaryValue;
using test::CreateValue;
namespace {
class CommandInstanceTest : public ::testing::Test {
protected:
void SetUp() override {
auto json = CreateDictionaryValue(R"({
'base': {
'reboot': {
'parameters': {},
'results': {}
}
},
'robot': {
'jump': {
'parameters': {
'height': {
'type': 'integer',
'minimum': 0,
'maximum': 100
},
'_jumpType': {
'type': 'string',
'enum': ['_withAirFlip', '_withSpin', '_withKick']
}
},
'progress': {'progress': 'integer'},
'results': {'testResult': 'integer'}
},
'speak': {
'parameters': {
'phrase': {
'type': 'string',
'enum': ['beamMeUpScotty', 'iDontDigOnSwine',
'iPityDaFool', 'dangerWillRobinson']
},
'volume': {
'type': 'integer',
'minimum': 0,
'maximum': 10
}
},
'results': {'foo': 'integer'}
}
}
})");
CHECK(dict_.LoadCommands(*json, nullptr, nullptr))
<< "Failed to parse test command dictionary";
}
CommandDictionary dict_;
};
} // anonymous namespace
TEST_F(CommandInstanceTest, Test) {
StringPropType str_prop;
IntPropType int_prop;
ValueMap params;
params["phrase"] =
str_prop.CreateValue(base::StringValue{"iPityDaFool"}, nullptr);
params["volume"] = int_prop.CreateValue(base::FundamentalValue{5}, nullptr);
CommandInstance instance{"robot.speak", CommandOrigin::kCloud,
dict_.FindCommand("robot.speak"), params};
EXPECT_TRUE(
instance.SetResults(*CreateDictionaryValue("{'foo': 239}"), nullptr));
EXPECT_EQ("", instance.GetID());
EXPECT_EQ("robot.speak", instance.GetName());
EXPECT_EQ(CommandOrigin::kCloud, instance.GetOrigin());
EXPECT_JSON_EQ("{'phrase': 'iPityDaFool', 'volume': 5}",
*instance.GetParameters());
EXPECT_JSON_EQ("{'foo': 239}", *instance.GetResults());
CommandInstance instance2{"base.reboot",
CommandOrigin::kLocal,
dict_.FindCommand("base.reboot"),
{}};
EXPECT_EQ(CommandOrigin::kLocal, instance2.GetOrigin());
}
TEST_F(CommandInstanceTest, SetID) {
CommandInstance instance{"base.reboot",
CommandOrigin::kLocal,
dict_.FindCommand("base.reboot"),
{}};
instance.SetID("command_id");
EXPECT_EQ("command_id", instance.GetID());
}
TEST_F(CommandInstanceTest, FromJson) {
auto json = CreateDictionaryValue(R"({
'name': 'robot.jump',
'id': 'abcd',
'parameters': {
'height': 53,
'_jumpType': '_withKick'
},
'results': {}
})");
std::string id;
auto instance = CommandInstance::FromJson(json.get(), CommandOrigin::kCloud,
dict_, &id, nullptr);
EXPECT_EQ("abcd", id);
EXPECT_EQ("abcd", instance->GetID());
EXPECT_EQ("robot.jump", instance->GetName());
EXPECT_JSON_EQ("{'height': 53, '_jumpType': '_withKick'}",
*instance->GetParameters());
}
TEST_F(CommandInstanceTest, FromJson_ParamsOmitted) {
auto json = CreateDictionaryValue("{'name': 'base.reboot'}");
auto instance = CommandInstance::FromJson(json.get(), CommandOrigin::kCloud,
dict_, nullptr, nullptr);
EXPECT_EQ("base.reboot", instance->GetName());
EXPECT_JSON_EQ("{}", *instance->GetParameters());
}
TEST_F(CommandInstanceTest, FromJson_NotObject) {
auto json = CreateValue("'string'");
ErrorPtr error;
auto instance = CommandInstance::FromJson(json.get(), CommandOrigin::kCloud,
dict_, nullptr, &error);
EXPECT_EQ(nullptr, instance.get());
EXPECT_EQ("json_object_expected", error->GetCode());
}
TEST_F(CommandInstanceTest, FromJson_NameMissing) {
auto json = CreateDictionaryValue("{'param': 'value'}");
ErrorPtr error;
auto instance = CommandInstance::FromJson(json.get(), CommandOrigin::kCloud,
dict_, nullptr, &error);
EXPECT_EQ(nullptr, instance.get());
EXPECT_EQ("parameter_missing", error->GetCode());
}
TEST_F(CommandInstanceTest, FromJson_UnknownCommand) {
auto json = CreateDictionaryValue("{'name': 'robot.scream'}");
ErrorPtr error;
auto instance = CommandInstance::FromJson(json.get(), CommandOrigin::kCloud,
dict_, nullptr, &error);
EXPECT_EQ(nullptr, instance.get());
EXPECT_EQ("invalid_command_name", error->GetCode());
}
TEST_F(CommandInstanceTest, FromJson_ParamsNotObject) {
auto json = CreateDictionaryValue(R"({
'name': 'robot.speak',
'parameters': 'hello'
})");
ErrorPtr error;
auto instance = CommandInstance::FromJson(json.get(), CommandOrigin::kCloud,
dict_, nullptr, &error);
EXPECT_EQ(nullptr, instance.get());
auto inner = error->GetInnerError();
EXPECT_EQ("json_object_expected", inner->GetCode());
EXPECT_EQ("command_failed", error->GetCode());
}
TEST_F(CommandInstanceTest, FromJson_ParamError) {
auto json = CreateDictionaryValue(R"({
'name': 'robot.speak',
'parameters': {
'phrase': 'iPityDaFool',
'volume': 20
}
})");
ErrorPtr error;
auto instance = CommandInstance::FromJson(json.get(), CommandOrigin::kCloud,
dict_, nullptr, &error);
EXPECT_EQ(nullptr, instance.get());
auto first = error->GetFirstError();
EXPECT_EQ("out_of_range", first->GetCode());
auto inner = error->GetInnerError();
EXPECT_EQ("invalid_parameter_value", inner->GetCode());
EXPECT_EQ("command_failed", error->GetCode());
}
TEST_F(CommandInstanceTest, ToJson) {
auto json = CreateDictionaryValue(R"({
'name': 'robot.jump',
'parameters': {
'height': 53,
'_jumpType': '_withKick'
},
'results': {}
})");
auto instance = CommandInstance::FromJson(json.get(), CommandOrigin::kCloud,
dict_, nullptr, nullptr);
EXPECT_TRUE(instance->SetProgress(*CreateDictionaryValue("{'progress': 15}"),
nullptr));
EXPECT_TRUE(instance->SetProgress(*CreateDictionaryValue("{'progress': 15}"),
nullptr));
instance->SetID("testId");
EXPECT_TRUE(instance->SetResults(*CreateDictionaryValue("{'testResult': 17}"),
nullptr));
json->MergeDictionary(CreateDictionaryValue(R"({
'id': 'testId',
'progress': {'progress': 15},
'state': 'inProgress',
'results': {'testResult': 17}
})").get());
auto converted = instance->ToJson();
EXPECT_PRED2([](const base::Value& val1,
const base::Value& val2) { return val1.Equals(&val2); },
*json, *converted);
}
} // namespace weave