diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:15:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 12:15:43 +0000 |
commit | f5f56e1a1c4d9e9496fcb9d81131066a964ccd23 (patch) | |
tree | 49e44c6f87febed37efb953ab5485aa49f6481a7 /src/lib/cc/tests/command_interpreter_unittests.cc | |
parent | Initial commit. (diff) | |
download | isc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.tar.xz isc-kea-f5f56e1a1c4d9e9496fcb9d81131066a964ccd23.zip |
Adding upstream version 2.4.1.upstream/2.4.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib/cc/tests/command_interpreter_unittests.cc')
-rw-r--r-- | src/lib/cc/tests/command_interpreter_unittests.cc | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/src/lib/cc/tests/command_interpreter_unittests.cc b/src/lib/cc/tests/command_interpreter_unittests.cc new file mode 100644 index 0000000..8738b92 --- /dev/null +++ b/src/lib/cc/tests/command_interpreter_unittests.cc @@ -0,0 +1,249 @@ +// Copyright (C) 2009-2023 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <gtest/gtest.h> + +#include <cc/command_interpreter.h> +#include <config/tests/data_def_unittests_config.h> +#include <log/logger_name.h> + +#include <boost/scoped_ptr.hpp> + +#include <fstream> + +using namespace isc::data; +using namespace isc::config; +using namespace std; + +namespace { + + +/// @brief Convenience method for creating elements from JSON string +/// +/// @param str string to be converted +/// @return Element structure +ElementPtr +el(const std::string& str) { + return (Element::fromJSON(str)); +} + +// This test verifies that that createAnswer method is able to generate +// various answers. +TEST(CommandInterpreterTest, createAnswer) { + ConstElementPtr answer; + + // By default the answer is a successful one. + answer = createAnswer(); + EXPECT_EQ("{ \"result\": 0 }", answer->str()); + + // Let's check if we can generate an error. + answer = createAnswer(CONTROL_RESULT_ERROR, "error"); + EXPECT_EQ("{ \"result\": 1, \"text\": \"error\" }", answer->str()); + + // This is expected to throw. When status code is non-zero (indicating error), + // textual explanation is mandatory. + EXPECT_THROW(createAnswer(CONTROL_RESULT_ERROR, ElementPtr()), CtrlChannelError); + EXPECT_THROW(createAnswer(CONTROL_RESULT_ERROR, Element::create(1)), CtrlChannelError); + + // Let's check if answer can be generate with some data in it. + ConstElementPtr arg = el("[ \"just\", \"some\", \"data\" ]"); + answer = createAnswer(CONTROL_RESULT_SUCCESS, arg); + EXPECT_EQ("{ \"arguments\": [ \"just\", \"some\", \"data\" ], \"result\": 0 }", + answer->str()); +} + +// This test checks whether parseAnswer is able to handle good and malformed +// answers. +TEST(CommandInterpreterTest, parseAnswer) { + ConstElementPtr answer; + ConstElementPtr arg; + int rcode; + + EXPECT_THROW(parseAnswer(rcode, ElementPtr()), CtrlChannelError); + EXPECT_THROW(parseAnswer(rcode, el("1")), CtrlChannelError); + EXPECT_THROW(parseAnswer(rcode, el("[]")), CtrlChannelError); + EXPECT_THROW(parseAnswer(rcode, el("{ }")), CtrlChannelError); + EXPECT_THROW(parseAnswer(rcode, el("{ \"something\": 1 }")), CtrlChannelError); + EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": [ 0 ] }")), CtrlChannelError); + EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": [ 1 ] }")), CtrlChannelError); + EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": [ 1, 1 ] }")), CtrlChannelError); + + answer = el("{ \"result\": 0 }"); + arg = parseAnswer(rcode, answer); + EXPECT_EQ(0, rcode); + EXPECT_TRUE(isNull(arg)); + + answer = el("{ \"result\": 3, \"text\": \"error\", \"arguments\": [ \"some\", \"data\" ] }"); + arg = parseAnswer(rcode, answer); + ASSERT_TRUE(arg); + EXPECT_EQ(3, rcode); + EXPECT_EQ("[ \"some\", \"data\" ]", arg->str()); +} + +// Checks if parseAnswerText can return the text +TEST(CommandInterpreterTest, parseAnswerText) { + ConstElementPtr answer; + ConstElementPtr arg; + int rcode; + + answer = el("{ \"result\": 5, \"text\": \"error\", \"arguments\": [ \"some\", \"data\" ] }"); + arg = parseAnswerText(rcode, answer); + ASSERT_TRUE(arg); + EXPECT_EQ(5, rcode); + EXPECT_EQ("error", arg->stringValue()); +} + +// This checks whether we can convert an answer to easily printable form. +TEST(CommandInterpreterTest, answerToText) { + ConstElementPtr answer; + + // Doing jolly good here. + answer = el("{ \"result\": 0 }"); + EXPECT_EQ("success(0)", answerToText(answer)); + + // Sometimes things don't go according to plan. + answer = el("{ \"result\": 1, \"text\": \"ho lee fuk sum ting wong\" }"); + EXPECT_EQ("failure(1), text=ho lee fuk sum ting wong", answerToText(answer)); +} + +// This test checks whether createCommand function is able to create commands +// with and without parameters. +TEST(CommandInterpreterTest, createCommand) { + ConstElementPtr command; + ConstElementPtr arg; + string service; + + command = createCommand("my_command"); + ASSERT_EQ("{ \"command\": \"my_command\" }", command->str()); + + arg = el("1"); + command = createCommand("my_command", arg); + ASSERT_EQ("{ \"arguments\": 1, \"command\": \"my_command\" }", + command->str()); + + arg = el("[ \"a\", \"b\" ]"); + command = createCommand("my_cmd", arg); + ASSERT_EQ("{ \"arguments\": [ \"a\", \"b\" ], \"command\": \"my_cmd\" }", + command->str()); + + arg = el("{ \"a\": \"map\" }"); + command = createCommand("foo", arg); + ASSERT_EQ("{ \"arguments\": { \"a\": \"map\" }, \"command\": \"foo\" }", + command->str()); + + command = createCommand("my_command", "my_service"); + ASSERT_EQ("{ \"command\": \"my_command\", " + "\"service\": [ \"my_service\" ] }", + command->str()); + + arg = el("1"); + command = createCommand("my_command", arg, "my_service"); + ASSERT_EQ("{ \"arguments\": 1, \"command\": \"my_command\", " + "\"service\": [ \"my_service\" ] }", + command->str()); + + arg = el("[ \"a\", \"b\" ]"); + command = createCommand("my_cmd", arg, "my_server"); + ASSERT_EQ("{ \"arguments\": [ \"a\", \"b\" ], " + "\"command\": \"my_cmd\", " + "\"service\": [ \"my_server\" ] }", + command->str()); + + arg = el("{ \"a\": \"map\" }"); + command = createCommand("foo", arg, "bar"); + ASSERT_EQ("{ \"arguments\": { \"a\": \"map\" }, " + "\"command\": \"foo\", " + "\"service\": [ \"bar\" ] }", + command->str()); +} + +// This test checks whether parseCommand function is able to parse various valid +// and malformed commands. +TEST(CommandInterpreterTest, parseCommand) { + ConstElementPtr arg; + std::string cmd; + + // should throw + EXPECT_THROW(parseCommand(arg, ElementPtr()), CtrlChannelError); + EXPECT_THROW(parseCommand(arg, el("1")), CtrlChannelError); + EXPECT_THROW(parseCommand(arg, el("{ }")), CtrlChannelError); + EXPECT_THROW(parseCommand(arg, el("{ \"not a command\": 1 }")), CtrlChannelError); + EXPECT_THROW(parseCommand(arg, el("{ \"command\": 1 }")), CtrlChannelError); + EXPECT_THROW(parseCommand(arg, el("{ \"command\": [] }")), CtrlChannelError); + EXPECT_THROW(parseCommand(arg, el("{ \"command\": [ 1 ] }")), CtrlChannelError); + EXPECT_THROW(parseCommand(arg, el("{ \"command\": \"my_command\", " + "\"unknown\": \"xyz\" }")), CtrlChannelError); + + cmd = parseCommand(arg, el("{ \"command\": \"my_command\" }")); + EXPECT_EQ("my_command", cmd); + EXPECT_FALSE(arg); + + // Include "service" to verify that it is not rejected. + cmd = parseCommand(arg, el("{ \"command\": \"my_command\", \"arguments\": 1, " + " \"service\": [ \"dhcp4\" ] }")); + ASSERT_TRUE(arg); + EXPECT_EQ("my_command", cmd); + EXPECT_EQ("1", arg->str()); + + parseCommand(arg, el("{ \"command\": \"my_command\", \"arguments\": " + "[ \"some\", \"argument\", \"list\" ] }")); + EXPECT_EQ("my_command", cmd); + ASSERT_TRUE(arg); + EXPECT_EQ("[ \"some\", \"argument\", \"list\" ]", arg->str()); + +} + +// This test checks whether parseCommandWithArgs function is able to parse +// various valid and malformed commands. +TEST(CommandInterpreterTest, parseCommandWithArgs) { + ConstElementPtr arg; + std::string cmd; + + // Arguments are required. + EXPECT_THROW(parseCommandWithArgs(arg, el("{ \"command\": \"my_command\" }")), + CtrlChannelError); + + // Arguments must be a map. + EXPECT_THROW(parseCommandWithArgs(arg, el("{ \"command\": \"my_command\", " + "\"arguments\": [ 1, 2, 3 ] }")), + CtrlChannelError); + + // Arguments must not be empty. + EXPECT_THROW(parseCommandWithArgs(arg, el("{ \"command\": \"my_command\", " + "\"arguments\": { } }")), + CtrlChannelError); + + // Command with unsupported parameter is rejected. + EXPECT_THROW(parseCommandWithArgs(arg, el("{ \"command\": \"my_command\", " + " \"arguments\": { \"arg1\": \"value1\" }, " + " \"unsupported\": 1 }")), + CtrlChannelError); + + + // Specifying arguments in non empty map should be successful. + EXPECT_NO_THROW( + cmd = parseCommandWithArgs(arg, el("{ \"command\": \"my_command\", " + " \"arguments\": { \"arg1\": \"value1\" } }")) + ); + ASSERT_TRUE(arg); + ASSERT_EQ(Element::map, arg->getType()); + auto arg1 = arg->get("arg1"); + ASSERT_TRUE(arg1); + ASSERT_EQ(Element::string, arg1->getType()); + EXPECT_EQ("value1", arg1->stringValue()); + EXPECT_EQ("my_command", cmd); + + // The "service" parameter should be allowed. + EXPECT_NO_THROW(parseCommandWithArgs(arg, el("{ \"command\": \"my_command\", " + " \"service\": [ \"dhcp4\" ], " + " \"arguments\": { \"arg1\": \"value1\" } }")) + ); + +} + +} |