diff --git a/src/lib/cc/Makefile.am b/src/lib/cc/Makefile.am index 663290657d..a86b5f430d 100644 --- a/src/lib/cc/Makefile.am +++ b/src/lib/cc/Makefile.am @@ -17,7 +17,6 @@ lib_LTLIBRARIES = libkea-cc.la libkea_cc_la_SOURCES = data.cc data.h libkea_cc_la_SOURCES += logger.cc logger.h nodist_libkea_cc_la_SOURCES = cc_messages.cc cc_messages.h -libkea_cc_la_SOURCES += proto_defs.cc proto_defs.h libkea_cc_la_LIBADD = $(top_builddir)/src/lib/log/libkea-log.la CLEANFILES = *.gcno *.gcda session_config.h cc_messages.cc cc_messages.h \ @@ -32,11 +31,6 @@ s-messages: cc_messages.mes $(top_builddir)/src/lib/log/compiler/message $(top_srcdir)/src/lib/cc/cc_messages.mes touch $@ -BUILT_SOURCES = session_config.h cc_messages.cc cc_messages.h proto_defs.h - -# This rule is here, but we added proto_defs.h to the git repo, -# so the script is no longer needed. -#proto_defs.h: $(top_srcdir)/src/lib/util/python/const2hdr.py proto_defs.cc -# $(PYTHON) $(top_srcdir)/src/lib/util/python/const2hdr.py $(srcdir)/proto_defs.cc $@ +BUILT_SOURCES = session_config.h cc_messages.cc cc_messages.h EXTRA_DIST = cc_messages.mes diff --git a/src/lib/cc/proto_defs.cc b/src/lib/cc/proto_defs.cc deleted file mode 100644 index 2806c2a475..0000000000 --- a/src/lib/cc/proto_defs.cc +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include - -namespace isc { -namespace cc { - -// Aside from defining the values for the C++ library, this file is also -// used as direct input of the generator of the python counterpart. Please, -// keep the syntax here simple and check the generated file -// (lib/python/isc/cc/proto_defs.py) is correct and sane. - -// The constants used in the CC protocol -// First the header names -const char* const CC_HEADER_TYPE = "type"; -const char* const CC_HEADER_FROM = "from"; -const char* const CC_HEADER_TO = "to"; -const char* const CC_HEADER_GROUP = "group"; -const char* const CC_HEADER_INSTANCE = "instance"; -const char* const CC_HEADER_SEQ = "seq"; -const char* const CC_HEADER_WANT_ANSWER = "want_answer"; -const char* const CC_HEADER_REPLY = "reply"; -// The commands in the "type" header -const char* const CC_COMMAND_SEND = "send"; -const char* const CC_COMMAND_SUBSCRIBE = "subscribe"; -const char* const CC_COMMAND_UNSUBSCRIBE = "unsubscribe"; -const char* const CC_COMMAND_GET_LNAME = "getlname"; -const char* const CC_COMMAND_PING = "ping"; -const char* const CC_COMMAND_PONG = "pong"; -const char* const CC_COMMAND_STOP = "stop"; -// The wildcards of some headers -const char* const CC_TO_WILDCARD = "*"; -const char* const CC_INSTANCE_WILDCARD = "*"; -// Prefixes for groups -const char* const CC_GROUP_NOTIFICATION_PREFIX = "notifications/"; -// Reply codes -const int CC_REPLY_NO_RECPT = -1; -const int CC_REPLY_SUCCESS = 0; -// Payload in the message -const char *const CC_PAYLOAD_LNAME = "lname"; -const char *const CC_PAYLOAD_RESULT = "result"; -const char *const CC_PAYLOAD_COMMAND = "command"; -const char *const CC_PAYLOAD_NOTIFICATION = "notification"; - -} -} diff --git a/src/lib/cc/proto_defs.h b/src/lib/cc/proto_defs.h deleted file mode 100644 index d7fac8d79e..0000000000 --- a/src/lib/cc/proto_defs.h +++ /dev/null @@ -1,73 +0,0 @@ -// This file is generated from ./proto_defs.cc -// by the const2hdr.py script. -// Do not edit, all changes will be lost. - -// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#ifndef KEA_COMMON_DEFS_H -#define KEA_COMMON_DEFS_H - -// \file proto_defs.h -// \brief Common shared constants - -// This file contains common definitions of constasts used across the sources. -// It includes, but is not limited to the definitions of messages sent from -// one process to another. Since the names should be self-explanatory and -// the variables here are used mostly to synchronize the same values across -// multiple programs, separate documentation for each variable is not provided. - -namespace isc { -namespace cc { - -// Aside from defining the values for the C++ library, this file is also -// used as direct input of the generator of the python counterpart. Please, -// keep the syntax here simple and check the generated file -// (lib/python/isc/cc/proto_defs.py) is correct and sane. - -// The constants used in the CC protocol -// First the header names -extern const char* const CC_HEADER_TYPE; -extern const char* const CC_HEADER_FROM; -extern const char* const CC_HEADER_TO; -extern const char* const CC_HEADER_GROUP; -extern const char* const CC_HEADER_INSTANCE; -extern const char* const CC_HEADER_SEQ; -extern const char* const CC_HEADER_WANT_ANSWER; -extern const char* const CC_HEADER_REPLY; -// The commands in the "type" header -extern const char* const CC_COMMAND_SEND; -extern const char* const CC_COMMAND_SUBSCRIBE; -extern const char* const CC_COMMAND_UNSUBSCRIBE; -extern const char* const CC_COMMAND_GET_LNAME; -extern const char* const CC_COMMAND_PING; -extern const char* const CC_COMMAND_PONG; -extern const char* const CC_COMMAND_STOP; -// The wildcards of some headers -extern const char* const CC_TO_WILDCARD; -extern const char* const CC_INSTANCE_WILDCARD; -// Prefixes for groups -extern const char* const CC_GROUP_NOTIFICATION_PREFIX; -// Reply codes -extern const int CC_REPLY_NO_RECPT; -extern const int CC_REPLY_SUCCESS; -// Payload in the message -extern const char *const CC_PAYLOAD_LNAME; -extern const char *const CC_PAYLOAD_RESULT; -extern const char *const CC_PAYLOAD_COMMAND; -extern const char *const CC_PAYLOAD_NOTIFICATION; - -} -} -#endif diff --git a/src/lib/config/ccsession.cc b/src/lib/config/ccsession.cc index 168434ea3e..6b8bf30b0a 100644 --- a/src/lib/config/ccsession.cc +++ b/src/lib/config/ccsession.cc @@ -53,70 +53,78 @@ using isc::data::JSONError; namespace isc { namespace config { -/// Creates a standard config/command protocol answer message +const char *CONTROL_COMMAND="command"; + +const char *CONTROL_RESULT="result"; +const char *CONTROL_TEXT="text"; +const char *CONTROL_ARGUMENTS="arguments"; + +// Full version, with status, text and arguments +ConstElementPtr +createAnswer(const int status_code, const std::string& text, + const ConstElementPtr& arg) { + if (status_code != 0 && text.empty()) { + isc_throw(CtrlChannelError, "Text has to be provided for status_code != 0"); + } + + ElementPtr answer = Element::createMap(); + ElementPtr result = Element::create(status_code); + answer->set(CONTROL_RESULT, result); + + if (!text.empty()) { + answer->set(CONTROL_TEXT, Element::create(text)); + } + if (arg) { + answer->set(CONTROL_ARGUMENTS, arg); + } + return (answer); +} + ConstElementPtr createAnswer() { - ElementPtr answer = Element::createMap(); - ElementPtr answer_content = Element::createList(); - answer_content->add(Element::create(isc::cc::CC_REPLY_SUCCESS)); - answer->set(isc::cc::CC_PAYLOAD_RESULT, answer_content); - - return (answer); + return (createAnswer(0, string(""), ConstElementPtr())); } ConstElementPtr -createAnswer(const int rcode, ConstElementPtr arg) { - if (rcode != 0 && (!arg || arg->getType() != Element::string)) { - isc_throw(CCSessionError, "Bad or no argument for rcode != 0"); +createAnswer(const int status_code, const std::string& text) { + return (createAnswer(status_code, text, ElementPtr())); +} + +ConstElementPtr +createAnswer(const int status_code, const ConstElementPtr& arg) { + return (createAnswer(status_code, "", arg)); +} + +ConstElementPtr +parseAnswer(int &rcode, const ConstElementPtr& msg) { + if (!msg) { + isc_throw(CtrlChannelError, "No answer specified"); } - ElementPtr answer = Element::createMap(); - ElementPtr answer_content = Element::createList(); - answer_content->add(Element::create(rcode)); - answer_content->add(arg); - answer->set(isc::cc::CC_PAYLOAD_RESULT, answer_content); - - return (answer); -} - -ConstElementPtr -createAnswer(const int rcode, const std::string& arg) { - ElementPtr answer = Element::createMap(); - ElementPtr answer_content = Element::createList(); - answer_content->add(Element::create(rcode)); - answer_content->add(Element::create(arg)); - answer->set(isc::cc::CC_PAYLOAD_RESULT, answer_content); - - return (answer); -} - -ConstElementPtr -parseAnswer(int &rcode, ConstElementPtr msg) { - if (msg && - msg->getType() == Element::map && - msg->contains(isc::cc::CC_PAYLOAD_RESULT)) { - ConstElementPtr result = msg->get(isc::cc::CC_PAYLOAD_RESULT); - if (result->getType() != Element::list) { - isc_throw(CCSessionError, "Result element in answer message is not a list"); - } else if (result->get(0)->getType() != Element::integer) { - isc_throw(CCSessionError, "First element of result is not an rcode in answer message"); - } - rcode = result->get(0)->intValue(); - if (result->size() > 1) { - if (rcode == 0 || result->get(1)->getType() == Element::string) { - return (result->get(1)); - } else { - isc_throw(CCSessionError, "Error description in result with rcode != 0 is not a string"); - } - } else { - if (rcode == 0) { - return (ElementPtr()); - } else { - isc_throw(CCSessionError, "Result with rcode != 0 does not have an error description"); - } - } - } else { - isc_throw(CCSessionError, "No result part in answer message"); + if (msg->getType() != Element::map) { + isc_throw(CtrlChannelError, + "Invalid answer Element specified, expected map"); } + if (!msg->contains(CONTROL_RESULT)) { + isc_throw(CtrlChannelError, + "Invalid answer specified, does not contain mandatory 'result'"); + } + + ConstElementPtr result = msg->get(CONTROL_RESULT); + if (result->getType() != Element::integer) { + isc_throw(CtrlChannelError, + "Result element in answer message is not a string"); + } + + rcode = result->intValue(); + + // If there are arguments, return them. + ConstElementPtr args = msg->get(CONTROL_ARGUMENTS); + if (args) { + return (args); + } + + // There are no arguments, let's try to return just the text status + return (msg->get(CONTROL_TEXT)); } ConstElementPtr @@ -126,37 +134,37 @@ createCommand(const std::string& command) { ConstElementPtr createCommand(const std::string& command, ConstElementPtr arg) { - ElementPtr cmd = Element::createMap(); - ElementPtr cmd_parts = Element::createList(); - cmd_parts->add(Element::create(command)); + ElementPtr query = Element::createMap(); + ElementPtr cmd = Element::create(command); + query->set(CONTROL_COMMAND, cmd); if (arg) { - cmd_parts->add(arg); + query->set(CONTROL_ARGUMENTS, arg); } - cmd->set(isc::cc::CC_PAYLOAD_COMMAND, cmd_parts); - return (cmd); + return (query); } std::string parseCommand(ConstElementPtr& arg, ConstElementPtr command) { - if (command && - command->getType() == Element::map && - command->contains(isc::cc::CC_PAYLOAD_COMMAND)) { - ConstElementPtr cmd = command->get(isc::cc::CC_PAYLOAD_COMMAND); - if (cmd->getType() == Element::list && - !cmd->empty() && - cmd->get(0)->getType() == Element::string) { - if (cmd->size() > 1) { - arg = cmd->get(1); - } else { - arg = Element::createMap(); - } - return (cmd->get(0)->stringValue()); - } else { - isc_throw(CCSessionError, "Command part in command message missing, empty, or not a list"); - } - } else { - isc_throw(CCSessionError, "Command Element empty or not a map with \"command\""); + if (!command) { + isc_throw(CtrlChannelError, "No command specified"); } + if (command->getType() != Element::map) { + isc_throw(CtrlChannelError, "Invalid command Element specified, expected map"); + } + if (!command->contains(CONTROL_COMMAND)) { + isc_throw(CtrlChannelError, + "Invalid answer specified, does not contain mandatory 'command'"); + } + + ConstElementPtr cmd = command->get(CONTROL_COMMAND); + if (cmd->getType() != Element::string) { + isc_throw(CtrlChannelError, + "'command' element in command message is not a string"); + } + + arg = command->get(CONTROL_ARGUMENTS); + + return (cmd->stringValue()); } namespace { diff --git a/src/lib/config/ccsession.h b/src/lib/config/ccsession.h index 6051bc15fc..802db92a66 100644 --- a/src/lib/config/ccsession.h +++ b/src/lib/config/ccsession.h @@ -19,7 +19,6 @@ #include #include -#include #include #include @@ -28,112 +27,97 @@ namespace isc { namespace config { -/// -/// \brief Creates a standard config/command level success answer message -/// (i.e. of the form { "result": [ 0 ] } -/// \return Standard command/config success answer message +extern const char *CONTROL_COMMAND; + +extern const char *CONTROL_RESULT; +extern const char *CONTROL_TEXT; +extern const char *CONTROL_ARGUMENTS; + +const int CONTROL_RESULT_SUCCESS = 0; +const int CONTROL_RESULT_ERROR = 1; + +/// @brief Creates a standard config/command level success answer message +/// (i.e. of the form { "result": 0 } +/// @return Standard command/config success answer message isc::data::ConstElementPtr createAnswer(); +/// @brief Creates a standard config/command level answer message +/// (i.e. of the form { "result": 1, "text": "Invalid command received" } /// -/// \brief Creates a standard config/command level answer message -/// (i.e. of the form { "result": [ rcode, arg ] } +/// @param status_code The return code (0 for success) +/// @param status_text A string to put into the "text" argument +/// @return Standard command/config answer message +isc::data::ConstElementPtr createAnswer(const int status_code, + const std::string& status_text); + +/// @brief Creates a standard config/command level answer message +/// (i.e. of the form { "result": status_code, "arguments": arg } +/// +/// @param status_code The return code (0 for success) +/// @param status_text A string to put into the "text" argument +/// @return Standard command/config answer message +isc::data::ConstElementPtr createAnswer(const int status_code, + const isc::data::ConstElementPtr& arg); + +/// @brief Creates a standard config/command level answer message +/// (i.e. of the form { "result": X, "[ rcode, arg ] } /// If rcode != 0, arg must be a StringElement /// -/// \param rcode The return code (0 for success) -/// \param arg For rcode == 0, this is an optional argument of any -/// Element type. For rcode == 1, this argument is mandatory, -/// and must be a StringElement containing an error description -/// \return Standard command/config answer message -isc::data::ConstElementPtr createAnswer(const int rcode, - isc::data::ConstElementPtr arg); +/// @param status_code The return code (0 for success) +/// @param arg For status_code == 0, this is an optional argument of any +/// Element type. For status_code == 1, this argument is mandatory, +/// and may be any type of ElementPtr. +/// @return Standard command/config answer message +isc::data::ConstElementPtr createAnswer(const int status_code, + const std::string& status, + const isc::data::ConstElementPtr& arg); +/// @brief Parses a standard config/command level answer message. /// -/// \brief Creates a standard config/command level answer message -/// (i.e. of the form { "result": [ rcode, arg ] } -/// -/// \param rcode The return code (0 for success) -/// \param arg A string to put into the StringElement argument -/// \return Standard command/config answer message -isc::data::ConstElementPtr createAnswer(const int rcode, - const std::string& arg); - -/// -/// Parses a standard config/command level answer message -/// -/// \param rcode This value will be set to the return code contained in +/// @param status_code This value will be set to the return code contained in /// the message -/// \param msg The message to parse -/// \return The optional argument in the message, or an empty ElementPtr +/// @param msg The message to parse +/// @return The optional argument in the message, or an empty ElementPtr /// if there was no argument. If rcode != 0, this contains a /// StringElement with the error description. -isc::data::ConstElementPtr parseAnswer(int &rcode, - isc::data::ConstElementPtr msg); +isc::data::ConstElementPtr parseAnswer(int &status_code, + const isc::data::ConstElementPtr& msg); +/// @brief Creates a standard config/command command message with no +/// argument (of the form { "command": "my_command" } /// -/// \brief Creates a standard config/command command message with no -/// argument (of the form { "command": [ "my_command" ] } -/// -/// \param command The command string -/// \return The created message +/// @param command The command string +/// @return The created message isc::data::ConstElementPtr createCommand(const std::string& command); +/// @brief Creates a standard config/command command message with the +/// given argument (of the form { "command": "my_command", "arguments": arg } /// -/// \brief Creates a standard config/command command message with the -/// given argument (of the form { "command": [ "my_command", arg ] } -/// -/// \param command The command string -/// \param arg The optional argument for the command. This can be of +/// @param command The command string +/// @param arg The optional argument for the command. This can be of /// any Element type, but it should conform to the .spec file. -/// \return The created message +/// @return The created message isc::data::ConstElementPtr createCommand(const std::string& command, isc::data::ConstElementPtr arg); -/// -/// \brief Parses the given command into a string containing the actual +/// @brief Parses the given command into a string containing the actual /// command and an ElementPtr containing the optional argument. /// -/// Raises a CCSessionError if this is not a well-formed command +/// @throw Raises a CtrlChannelError if this is not a well-formed command /// -/// Example code: (command_message is a ConstElementPtr that is -/// passed here) -/// \code -/// ElementPtr command_message = Element::fromJSON("{ \"command\": [\"foo\", { \"bar\": 123 } ] }"); -/// try { -/// ConstElementPtr args; -/// std::string command_str = parseCommand(args, command_message); -/// if (command_str == "foo") { -/// std::cout << "The command 'foo' was given" << std::endl; -/// if (args->contains("bar")) { -/// std::cout << "It had argument name 'bar' set, which has" -/// << "value " -/// << args->get("bar")->intValue(); -/// } -/// } else { -/// std::cout << "Unknown command '" << command_str << std::endl; -/// } -/// } catch (CCSessionError cse) { -/// std::cerr << "Bad command in CC Session: " -/// << cse.what() << std::endl; -/// } -/// \endcode -/// -/// \param arg This value will be set to the ElementPtr pointing to +/// @param arg This value will be set to the ElementPtr pointing to /// the argument, or to an empty Map (ElementPtr) if there was none. -/// \param command The command message containing the command (as made +/// @param command The command message containing the command (as made /// by createCommand() /// \return The command name std::string parseCommand(isc::data::ConstElementPtr& arg, isc::data::ConstElementPtr command); - -/// -/// \brief A standard cc session exception that is thrown if a function +/// @brief A standard control channel exception that is thrown if a function /// is there is a problem with one of the messages -/// -// todo: include types and called function in the exception -class CCSessionError : public isc::Exception { +class CtrlChannelError : public isc::Exception { public: - CCSessionError(const char* file, size_t line, const char* what) : + CtrlChannelError(const char* file, size_t line, const char* what) : isc::Exception(file, line, what) {} }; diff --git a/src/lib/config/tests/ccsession_unittests.cc b/src/lib/config/tests/ccsession_unittests.cc index ab2ce535ce..c6fe8c7eb9 100644 --- a/src/lib/config/tests/ccsession_unittests.cc +++ b/src/lib/config/tests/ccsession_unittests.cc @@ -24,7 +24,6 @@ using namespace isc::data; using namespace isc::config; -using namespace isc::cc; using namespace std; namespace { @@ -50,16 +49,17 @@ protected: TEST_F(CCSessionTest, createAnswer) { ConstElementPtr answer; answer = createAnswer(); - EXPECT_EQ("{ \"result\": [ 0 ] }", answer->str()); + EXPECT_EQ("{ \"result\": 0 }", answer->str()); answer = createAnswer(1, "error"); - EXPECT_EQ("{ \"result\": [ 1, \"error\" ] }", answer->str()); + EXPECT_EQ("{ \"result\": 1, \"text\": \"error\" }", answer->str()); - EXPECT_THROW(createAnswer(1, ElementPtr()), CCSessionError); - EXPECT_THROW(createAnswer(1, Element::create(1)), CCSessionError); + EXPECT_THROW(createAnswer(1, ElementPtr()), CtrlChannelError); + EXPECT_THROW(createAnswer(1, Element::create(1)), CtrlChannelError); ConstElementPtr arg = el("[ \"just\", \"some\", \"data\" ]"); answer = createAnswer(0, arg); - EXPECT_EQ("{ \"result\": [ 0, [ \"just\", \"some\", \"data\" ] ] }", answer->str()); + EXPECT_EQ("{ \"arguments\": [ \"just\", \"some\", \"data\" ], \"result\": 0 }", + answer->str()); } TEST_F(CCSessionTest, parseAnswer) { @@ -67,27 +67,26 @@ TEST_F(CCSessionTest, parseAnswer) { ConstElementPtr arg; int rcode; - EXPECT_THROW(parseAnswer(rcode, ElementPtr()), CCSessionError); - EXPECT_THROW(parseAnswer(rcode, el("1")), CCSessionError); - EXPECT_THROW(parseAnswer(rcode, el("[]")), CCSessionError); - EXPECT_THROW(parseAnswer(rcode, el("{ }")), CCSessionError); - EXPECT_THROW(parseAnswer(rcode, el("{ \"something\": 1 }")), CCSessionError); - EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": 0 }")), CCSessionError); - EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": 1 }")), CCSessionError); - EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": [ 1 ] }")), CCSessionError); - EXPECT_THROW(parseAnswer(rcode, el("{ \"result\": [ 1, 1 ] }")), CCSessionError); + 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 ] }"); + answer = el("{ \"result\": 0 }"); arg = parseAnswer(rcode, answer); EXPECT_EQ(0, rcode); EXPECT_TRUE(isNull(arg)); - answer = el("{ \"result\": [ 1, \"error\"] }"); + answer = el("{ \"result\": 1, \"text\": \"error\" }"); arg = parseAnswer(rcode, answer); EXPECT_EQ(1, rcode); EXPECT_EQ("error", arg->stringValue()); - answer = el("{ \"result\": [ 0, [ \"just\", \"some\", \"data\" ] ] }"); + answer = el("{ \"result\": 0, \"arguments\": [ \"just\", \"some\", \"data\" ] }"); arg = parseAnswer(rcode, answer); EXPECT_EQ(0, rcode); EXPECT_EQ("[ \"just\", \"some\", \"data\" ]", arg->str()); @@ -98,19 +97,22 @@ TEST_F(CCSessionTest, createCommand) { ConstElementPtr arg; command = createCommand("my_command"); - ASSERT_EQ("{ \"command\": [ \"my_command\" ] }", command->str()); + ASSERT_EQ("{ \"command\": \"my_command\" }", command->str()); arg = el("1"); command = createCommand("my_command", arg); - ASSERT_EQ("{ \"command\": [ \"my_command\", 1 ] }", command->str()); + ASSERT_EQ("{ \"arguments\": 1, \"command\": \"my_command\" }", + command->str()); arg = el("[ \"a\", \"b\" ]"); command = createCommand("my_cmd", arg); - ASSERT_EQ("{ \"command\": [ \"my_cmd\", [ \"a\", \"b\" ] ] }", command->str()); + ASSERT_EQ("{ \"arguments\": [ \"a\", \"b\" ], \"command\": \"my_cmd\" }", + command->str()); arg = el("{ \"a\": \"map\" }"); command = createCommand("foo", arg); - ASSERT_EQ("{ \"command\": [ \"foo\", { \"a\": \"map\" } ] }", command->str()); + ASSERT_EQ("{ \"arguments\": { \"a\": \"map\" }, \"command\": \"foo\" }", + command->str()); } TEST_F(CCSessionTest, parseCommand) { @@ -118,24 +120,26 @@ TEST_F(CCSessionTest, parseCommand) { std::string cmd; // should throw - EXPECT_THROW(parseCommand(arg, ElementPtr()), CCSessionError); - EXPECT_THROW(parseCommand(arg, el("1")), CCSessionError); - EXPECT_THROW(parseCommand(arg, el("{ }")), CCSessionError); - EXPECT_THROW(parseCommand(arg, el("{ \"not a command\": 1 }")), CCSessionError); - EXPECT_THROW(parseCommand(arg, el("{ \"command\": 1 }")), CCSessionError); - EXPECT_THROW(parseCommand(arg, el("{ \"command\": [] }")), CCSessionError); - EXPECT_THROW(parseCommand(arg, el("{ \"command\": [ 1 ] }")), CCSessionError); + 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); - cmd = parseCommand(arg, el("{ \"command\": [ \"my_command\" ] }")); + cmd = parseCommand(arg, el("{ \"command\": \"my_command\" }")); EXPECT_EQ("my_command", cmd); - EXPECT_EQ(*arg, *Element::createMap()); + EXPECT_FALSE(arg); - cmd = parseCommand(arg, el("{ \"command\": [ \"my_command\", 1 ] }")); + cmd = parseCommand(arg, el("{ \"command\": \"my_command\", \"arguments\": 1 }")); + ASSERT_TRUE(arg); EXPECT_EQ("my_command", cmd); EXPECT_EQ("1", arg->str()); - parseCommand(arg, el("{ \"command\": [ \"my_command\", [ \"some\", \"argument\", \"list\" ] ] }")); + 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()); } diff --git a/src/lib/dhcpsrv/testutils/config_result_check.cc b/src/lib/dhcpsrv/testutils/config_result_check.cc index 61d0c3748d..b56bc9e537 100644 --- a/src/lib/dhcpsrv/testutils/config_result_check.cc +++ b/src/lib/dhcpsrv/testutils/config_result_check.cc @@ -12,7 +12,7 @@ // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. -#include +#include #include #include #include @@ -28,15 +28,16 @@ using namespace isc::data; bool errorContainsPosition(ConstElementPtr error_element, const std::string& file_name) { - if (error_element->contains(isc::cc::CC_PAYLOAD_RESULT)) { - ConstElementPtr result = error_element->get(isc::cc::CC_PAYLOAD_RESULT); - if ((result->getType() != Element::list) || (result->size() < 2) || - (result->get(1)->getType() != Element::string)) { + if (error_element->contains(isc::config::CONTROL_RESULT)) { + ConstElementPtr result = error_element->get(isc::config::CONTROL_RESULT); + ConstElementPtr text = error_element->get(isc::config::CONTROL_TEXT); + if (!result || (result->getType() != Element::integer) || !text + || (text->getType() != Element::string)) { return (false); } // Get the error message in the textual format. - std::string error_string = result->get(1)->stringValue(); + std::string error_string = text->stringValue(); // The position of the data element causing an error has the following // format: ::. The has been specified