blob: 76a3246578682b552164dcce885af480e1f4cbd8 [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 "buffet/commands/command_manager.h"
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/json/json_writer.h>
#include <chromeos/bind_lambda.h>
#include <gtest/gtest.h>
#include "buffet/commands/unittest_utils.h"
namespace buffet {
using unittests::CreateDictionaryValue;
namespace {
const char kTestBaseCommands[] = R"({
'base': {
'reboot': {
'parameters': {'delay': 'integer'},
'results': {}
},
'shutdown': {
'parameters': {},
'results': {}
}
}
})";
const char kTestVendorCommands[] = R"({
'robot': {
'_jump': {
'parameters': {'height': 'integer'},
'results': {}
},
'_speak': {
'parameters': {'phrase': 'string'},
'results': {}
}
}
})";
const char kTestTestCommands[] = R"({
'test': {
'_yo': {
'parameters': {'name': 'string'},
'results': {}
}
}
})";
static void SaveJsonToFile(const base::DictionaryValue& dict,
const base::FilePath& file_path) {
std::string json;
base::JSONWriter::Write(&dict, &json);
const int bytes_to_write = static_cast<int>(json.size());
CHECK_EQ(bytes_to_write, WriteFile(file_path, json.data(), bytes_to_write));
}
static base::FilePath SaveJsonToTempFile(const base::DictionaryValue& dict) {
base::FilePath temp_file;
base::CreateTemporaryFile(&temp_file);
SaveJsonToFile(dict, temp_file);
return temp_file;
}
} // namespace
TEST(CommandManager, Empty) {
CommandManager manager;
EXPECT_TRUE(manager.GetCommandDictionary().IsEmpty());
}
TEST(CommandManager, LoadBaseCommandsJSON) {
CommandManager manager;
auto json = CreateDictionaryValue(kTestBaseCommands);
EXPECT_TRUE(manager.LoadBaseCommands(*json, nullptr));
}
TEST(CommandManager, LoadBaseCommandsFile) {
CommandManager manager;
auto json = CreateDictionaryValue(kTestBaseCommands);
base::FilePath temp_file = SaveJsonToTempFile(*json);
EXPECT_TRUE(manager.LoadBaseCommands(temp_file, nullptr));
base::DeleteFile(temp_file, false);
}
TEST(CommandManager, LoadCommandsJSON) {
CommandManager manager;
auto json = CreateDictionaryValue(kTestVendorCommands);
EXPECT_TRUE(manager.LoadCommands(*json, "category", nullptr));
}
TEST(CommandManager, LoadCommandsFile) {
CommandManager manager;
// Load some standard command definitions first.
auto json = CreateDictionaryValue(R"({
'base': {
'reboot': {
'parameters': {'delay': 'integer'},
'results': {}
},
'shutdown': {
'parameters': {},
'results': {}
}
}
})");
manager.LoadBaseCommands(*json, nullptr);
// Load device-supported commands.
json = CreateDictionaryValue(R"({
'base': {
'reboot': {
'parameters': {'delay': 'integer'},
'results': {}
}
},
'robot': {
'_jump': {
'parameters': {'height': 'integer'},
'results': {}
}
}
})");
base::FilePath temp_file = SaveJsonToTempFile(*json);
EXPECT_TRUE(manager.LoadCommands(temp_file, nullptr));
base::DeleteFile(temp_file, false);
EXPECT_EQ(2, manager.GetCommandDictionary().GetSize());
EXPECT_NE(nullptr, manager.GetCommandDictionary().FindCommand("base.reboot"));
EXPECT_NE(nullptr, manager.GetCommandDictionary().FindCommand("robot._jump"));
}
TEST(CommandManager, ShouldLoadStandardAndTestDefinitions) {
CommandManager manager;
base::ScopedTempDir temp;
CHECK(temp.CreateUniqueTempDir());
base::FilePath base_path{temp.path().Append("base_defs")};
base::FilePath test_path{temp.path().Append("test_defs")};
base::FilePath base_commands_path{base_path.Append("commands")};
base::FilePath test_commands_path{test_path.Append("commands")};
CHECK(CreateDirectory(base_commands_path));
CHECK(CreateDirectory(test_commands_path));
SaveJsonToFile(*CreateDictionaryValue(kTestBaseCommands),
base_path.Append("gcd.json"));
SaveJsonToFile(*CreateDictionaryValue(kTestVendorCommands),
base_commands_path.Append("category.json"));
SaveJsonToFile(*CreateDictionaryValue(kTestTestCommands),
test_commands_path.Append("test.json"));
manager.Startup(base_path, test_path);
EXPECT_EQ(3, manager.GetCommandDictionary().GetSize());
EXPECT_NE(nullptr,
manager.GetCommandDictionary().FindCommand("robot._jump"));
EXPECT_NE(nullptr,
manager.GetCommandDictionary().FindCommand("robot._speak"));
EXPECT_NE(nullptr,
manager.GetCommandDictionary().FindCommand("test._yo"));
}
TEST(CommandManager, UpdateCommandVisibility) {
CommandManager manager;
int update_count = 0;
auto on_command_change = [&update_count]() { update_count++; };
manager.AddOnCommandDefChanged(base::Bind(on_command_change));
auto json = CreateDictionaryValue(R"({
'foo': {
'_baz': {
'parameters': {},
'results': {}
},
'_bar': {
'parameters': {},
'results': {}
}
},
'bar': {
'_quux': {
'parameters': {},
'results': {},
'visibility': 'none'
}
}
})");
ASSERT_TRUE(manager.LoadCommands(*json, "test", nullptr));
EXPECT_EQ(1, update_count);
const CommandDictionary& dict = manager.GetCommandDictionary();
EXPECT_TRUE(manager.SetCommandVisibility(
{"foo._baz"}, CommandDefinition::Visibility::GetLocal(), nullptr));
EXPECT_EQ(2, update_count);
EXPECT_EQ("local", dict.FindCommand("foo._baz")->GetVisibility().ToString());
EXPECT_EQ("all", dict.FindCommand("foo._bar")->GetVisibility().ToString());
EXPECT_EQ("none", dict.FindCommand("bar._quux")->GetVisibility().ToString());
chromeos::ErrorPtr error;
ASSERT_FALSE(manager.SetCommandVisibility(
{"foo._baz", "foo._bar", "test.cmd"},
CommandDefinition::Visibility::GetLocal(), &error));
EXPECT_EQ(errors::commands::kInvalidCommandName, error->GetCode());
EXPECT_EQ("Command 'test.cmd' is unknown", error->GetMessage());
// The visibility state of commands shouldn't have changed.
EXPECT_EQ(2, update_count);
EXPECT_EQ("local", dict.FindCommand("foo._baz")->GetVisibility().ToString());
EXPECT_EQ("all", dict.FindCommand("foo._bar")->GetVisibility().ToString());
EXPECT_EQ("none", dict.FindCommand("bar._quux")->GetVisibility().ToString());
EXPECT_TRUE(manager.SetCommandVisibility(
{"foo._baz", "bar._quux"}, CommandDefinition::Visibility::GetCloud(),
nullptr));
EXPECT_EQ(3, update_count);
EXPECT_EQ("cloud", dict.FindCommand("foo._baz")->GetVisibility().ToString());
EXPECT_EQ("all", dict.FindCommand("foo._bar")->GetVisibility().ToString());
EXPECT_EQ("cloud", dict.FindCommand("bar._quux")->GetVisibility().ToString());
}
} // namespace buffet