if test "x$enable_shell" != xno ; then
# If kea-shell is enabled, we really need python. 2.7 or anything newer will do.
- AM_PATH_PYTHON([2.7])
+ AM_PATH_PYTHON([3], [found="yes"], [found="no"])
+ if test "x$found" = xno ; then
+ AM_PATH_PYTHON([2.7])
+ fi
else
PYTHON=no
fi
src/bin/admin/tests/cql_tests.sh
src/bin/agent/tests/test_libraries.h
src/bin/shell/Makefile
+ src/bin/shell/kea-shell
src/bin/shell/tests/Makefile
src/bin/shell/tests/shell_process_tests.sh
+ src/bin/shell/tests/shell_unittest.py
src/hooks/Makefile
src/hooks/dhcp/Makefile
src/hooks/dhcp/user_chk/Makefile
])
AC_CONFIG_COMMANDS([permissions], [
+ chmod +x src/bin/admin/kea-admin
chmod +x src/bin/dhcp4/tests/dhcp4_process_tests.sh
chmod +x src/bin/dhcp6/tests/dhcp6_process_tests.sh
chmod +x src/bin/keactrl/keactrl
chmod +x src/bin/keactrl/tests/keactrl_tests.sh
- chmod +x src/bin/admin/kea-admin
+ chmod +x src/bin/shell/kea-shell
+ chmod +x src/bin/shell/tests/shell_process_tests.sh
+ chmod +x src/bin/shell/tests/shell_unittest.py
chmod +x src/lib/dns/gen-rdatacode.py
chmod +x src/lib/log/tests/console_test.sh
chmod +x src/lib/log/tests/destination_test.sh
cat >> config.report << END
Python:
+ PYTHON: ${PYTHON}
PYTHON_VERSION: ${PYTHON_VERSION}
END
noinst_SCRIPTS = ca_process_tests.sh
EXTRA_DIST = ca_process_tests.sh.in
-noinst_LTLIBRARIES = libbasic.la
# test using command-line arguments, so use check-local target instead of TESTS
check-local:
TESTS =
if HAVE_GTEST
+noinst_LTLIBRARIES = libbasic.la
+
TESTS += ca_unittests
ca_unittests_SOURCES = ca_cfg_mgr_unittests.cc
if KEA_SHELL
# Kea-shell is enabled, here are proper rules for it.
-kea_shell_PYTHON = kea-shell.py kea_conn.py kea_connector2.py kea_connector3.py
+kea_shell_PYTHON = kea_conn.py kea_connector2.py kea_connector3.py
kea_shelldir = @localstatedir@/@PACKAGE@
bin_SCRIPTS = kea-shell
else
# Kea-shell is disabled, simply keep the files for make dist
-EXTRA_DIST += kea-shell.py kea_conn.py kea_connector2.py kea_connector3.py
+EXTRA_DIST += kea-shell kea_conn.py kea_connector2.py kea_connector3.py
endif
-CLEANFILES = kea-shell kea-shell.pyc
-
+CLEANFILES = *.pyc
man_MANS = kea-shell.8
DISTCLEANFILES = $(man_MANS)
endif
-# This is done here since configure.ac AC_OUTPUT doesn't expand certain variables.
-kea-shell: kea-shell.py
- $(SED) "s|@@PYTHONPATH@@|@pyexecdir@|" kea-shell.py > kea-shell.tmp
- $(SED) "s|REPORTED_VERSION|@PACKAGE_VERSION@|" kea-shell.tmp >$@
- rm -f kea-shell.tmp
- chmod a+x $@
-
install-data-local:
$(mkinstalldirs) $(DESTDIR)/@localstatedir@/@PACKAGE@
--- /dev/null
+#!@PYTHON@
+
+# Copyright (C) 2017 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/.
+
+"""
+Text client for Control Agent process
+"""
+
+# First, let's import the right kea_connector.
+# We have two versions: one for python 2.x and another for python 3.x.
+# Sadly, there's no unified way to handle http connections. The recommended
+# way is to use Requests (http://docs.python-requests.org/en/master/), but
+# that's a stand alone package that requires separate installation. One of
+# the design requirements was to not require any additional packages, so
+# the code uses standard libraries available in python. Hence two versions.
+import sys
+import signal
+import argparse
+
+from kea_conn import CARequest # CAResponse
+
+if sys.version_info[0] == 2:
+ # This is Python 2.x
+ import kea_connector2 as kea_connector
+elif sys.version_info[0] == 3:
+ # This is Python 3.x
+ import kea_connector3 as kea_connector
+else:
+ # This is... have no idea what it is.
+ raise SystemExit("Unknown python version:" + str(sys.version_info[0]))
+
+def timeout_handler(signum, frame):
+ """Connection timeoout handler"""
+ del signum, frame
+ print("Connection timeout")
+ sys.exit(1)
+
+VERSION = "@PACKAGE_VERSION@"
+
+def shell_body():
+ """
+ Second step: Need to parse command line parameters. We will use
+ argparse for that purpose. It does great job with having default
+ values, taking care of the help and sanity checking input
+ parameters.
+ """
+ parser = argparse.ArgumentParser(description='kea-shell is a simple text '
+ 'client that uses REST interface to '
+ 'connect to Kea Control Agent.')
+ parser.add_argument('--host', type=str, default='127.0.0.1',
+ help='hostname of the CA to connect to '
+ '(defaul:; 127.0.0.1)')
+ parser.add_argument('--port', type=int, default=8000,
+ help='TCP port of the CA to connect to '
+ '(default: 8000)')
+ parser.add_argument('--timeout', type=int, default='10',
+ help='Timeout (in seconds) when attempting to '
+ 'connect to CA (default: 10)')
+ parser.add_argument('command', type=str, nargs="?",
+ default='list-commands',
+ help='command to be executed. If not specified, '
+ '"list-commands" is used')
+ parser.add_argument('-v', action="store_true", help="Prints version")
+ cmd_args = parser.parse_args()
+
+ if cmd_args.v:
+ print(VERSION)
+ exit(0)
+
+ # Ok, now time to put the parameters parsed into the structure to be
+ # used by the connection.
+ params = CARequest()
+ params.command = cmd_args.command
+ params.http_host = cmd_args.host
+ params.http_port = cmd_args.port
+ params.timeout = cmd_args.timeout
+ params.version = VERSION
+
+ params.generate_body()
+ params.generate_headers()
+
+ # Load command processor
+ # @todo - command specific processing will be added as part of
+ # future work (either #5138 or #5139, whichever is implemented
+ # first)
+
+ # Read parameters from stdin (they're optional for some commands)
+ for line in sys.stdin:
+ params.params += line
+
+ # Set the timeout timer. If the connection takes too long,
+ # it will send a signal to us.
+ signal.signal(signal.SIGALRM, timeout_handler)
+ signal.alarm(params.timeout)
+
+ # Ok, everything is ready. Let's send the command and get a response.
+ try:
+ resp = kea_connector.send_to_control_agent(params)
+ except Exception as exc:
+ print("Failed to run: " + str(exc))
+ sys.exit(1)
+
+ resp.print_response()
+
+ sys.exit(0)
+
+if __name__ == "__main__":
+ shell_body()
+++ /dev/null
-#!/usr/bin/python
-
-# This is going to be replaced with the actual version (see kea-shell target
-# in Makefile.am)
-VERSION = "REPORTED_VERSION"
-
-# First, let's import the right kea_connector.
-# We have two versions: one for python 2.x and another for python 3.x.
-# Sadly, there's no unified way to handle http connections. The recommended
-# way is to use Requests (http://docs.python-requests.org/en/master/), but
-# that's a stand alone package that requires separate installation. One of
-# the design requirements was to not require any additional packages, so
-# the code uses standard libraries available in python. Hence two versions.
-import sys
-import signal
-import argparse
-
-if (sys.version_info[0] == 2):
- # This is Python 2.x
- import kea_connector2 as kea_connector
-else:
- if (sys.version_info[0] == 3):
- # This is Python 3.x
- import kea_connector3 as kea_connector
- else:
- # This is... have no idea what it is.
- raise SystemExit("Unknown python version:" + str(sys.version_info[0]))
-
-from kea_conn import CARequest, CAResponse
-
-# Second step: Need to parse command line parameters. We will use argparse for
-# that purpose. It does great job with having default values, taking care of
-# the help and sanity checking input parameters.
-
-parser = argparse.ArgumentParser(description='kea-shell is a simple text client that uses REST '
- 'interface to connect to Kea Control Agent.')
-parser.add_argument('--host', type=str, default='127.0.0.1',
- help='hostname of the CA to connect to (default; 127.0.0.1)')
-parser.add_argument('--port', type=int, default=8000,
- help='TCP port of the CA to connect to (default: 8000)')
-parser.add_argument('--timeout', type=int, default='10',
- help='Timeout (in seconds) when attempting to connect to CA (default: 10)')
-parser.add_argument('command', type=str, nargs="?", default='list-commands',
- help='command to be executed. If not specified, "list-commands" is used')
-parser.add_argument('-v', action="store_true", help="Prints version")
-cmd_args = parser.parse_args()
-
-if (cmd_args.v):
- print (VERSION)
- exit(0)
-
-# Ok, now time to put the parameters parsed into the structure to be used by the
-# connection.
-params = CARequest()
-params.command = cmd_args.command
-params.http_host = cmd_args.host
-params.http_port = cmd_args.port
-params.timeout = cmd_args.timeout
-params.version = VERSION
-
-params.generateBody()
-params.generateHeaders()
-
-conn = kea_connector.KeaConnector()
-
-def timeout_handler(signum, frame):
- print ("Connection timeout")
- sys.exit(1)
-
-# Load command processor
-# @todo - command specific processing will be added as part of future work
-# (either #5138 or #5139, whichever is implemented first)
-
-# Read parameters from stdin (they're optional for some commands)
-for line in sys.stdin:
- params.params += line
-
-# Set the timeout timer. If the connection takes too long,
-# it will send a signal to us.
-signal.signal(signal.SIGALRM, timeout_handler)
-signal.alarm(params.timeout)
-
-# Ok, everything is ready. Let's send the command and get a response.
-try:
- resp = conn.sendCA(params)
-except Exception as e:
- print("Failed to run: " + str(e))
- sys.exit(1)
-
-resp.printResp()
-
-sys.exit(0)
<cmdsynopsis>
<command>kea-shell</command>
<arg><option>-h</option></arg>
+ <arg><option>-v</option></arg>
<arg><option>--host</option></arg>
<arg><option>--port</option></arg>
- <arg><option>-v</option></arg>
+ <arg><option>--timeout</option></arg>
<arg><option>command</option></arg>
</cmdsynopsis>
</refsynopsisdiv>
Kea Control Agent (CA). It takes command as a command-line parameter
that is being sent to CA with proper JSON
encapsulation. Optional parameters may be specified on the
- stdin. The request it sent of HTTP and a response is
- retrieved. That response is printed out on stdout.
+ standard input. The request it sent of HTTP and a response is
+ retrieved. That response is displayed out on the standard output.
</para>
</refsect1>
<variablelist>
<varlistentry>
- <term><option>-v</option></term>
+ <term><option>-h</option></term>
<listitem><para>
- Display the version.
+ Displays help regarding command line parameters.
</para></listitem>
</varlistentry>
<varlistentry>
- <term><option>-h</option></term>
+ <term><option>-v</option></term>
<listitem><para>
- Displays help regarding command line parameters.
+ Display the version.
</para></listitem>
</varlistentry>
-#!/usr/bin/python
+# Copyright (C) 2017 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/.
-# This file contains classes used for communication with Control Agent.
+"""
+This file contains classes used for communication with Control Agent.
+"""
-# This class defines the HTTP request to be sent.
-# The supported parameters listed are:
-# - path (specifies the path on the server, CA uses only /)
-# - http_host - hostname of the CA
-# - http-port - TCP port of the CA
-# - command - specifies the command to send (e.g. list-commands)
-# - timeout - timeout (in ms)
-# - headers - extra HTTP headers may be added here
-# - version - version to be reported in HTTP header
class CARequest:
+ """
+ This class defines the HTTP request to be sent.
+ The supported parameters listed are:
+ - path (specifies the path on the server, CA uses only /)
+ - http_host - hostname of the CA
+ - http-port - TCP port of the CA
+ - command - specifies the command to send (e.g. list-commands)
+ - timeout - timeout (in ms)
+ - headers - extra HTTP headers may be added here
+ - version - version to be reported in HTTP header
+ """
path = '/'
http_host = ''
http_port = 0
params = ''
headers = {}
version = ""
+ # This is a storage for generated command (input data to be sent over POST)
+ content = ''
- # Generates the content, out of specified command line
- # and optional content.
- # @todo: Add support for parameters
- # this stores the output in self.content
- def generateBody(self):
+ def generate_body(self):
+ """
+ Generates the content, out of specified command line
+ and optional content.
+ @todo: Add support for parameters
+ this stores the output in self.content
+ """
self.content = '{ "command": "' + self.command + '"'
- if (len(self.params)):
+ if len(self.params):
self.content += ', "parameters": { ' + self.params + ' }'
self.content += ' }'
- # Generate HTTP headers
- #
- # In particular, this method generates Content-Length and its value.
- def generateHeaders(self):
+ def generate_headers(self):
+ """
+ Generate HTTP headers
+
+ In particular, this method generates Content-Length and its value.
+ """
self.headers['Content-Type'] = 'application/json'
self.headers['User-Agent'] = "Kea-shell/%s"%(self.version)
self.headers['Accept'] = '*/*'
self.headers['Content-Length'] = "%d"%(len(self.content))
- # This is a storage for generated command (input data to be sent over POST)
- content = ''
-# This class represents the HTTP response
class CAResponse:
+ """
+ This class represents the HTTP response
+ """
- # Constructor
- #
- # Three mandatory parameters are:
- # status - numerical number the describe the status (e.g. 200 = OK)
- # reason - textual explanation of what happened
- # body - the actual body structure of the response
def __init__(self, status, reason, body):
+ """
+ Constructor
+
+ Three mandatory parameters are:
+ status - numerical number the describe the status (e.g. 200 = OK)
+ reason - textual explanation of what happened
+ body - the actual body structure of the response
+ """
self.status = status
self.reason = reason
self.body = body
reason = ''
body = ''
- # Used for debugging
- #
- # if defug is true, this prints even more information
- def printResp(self, debug = False):
- if (debug):
+ def print_response(self, debug=False):
+ """
+ Used for debugging
+
+ if debug is true, this prints even more information
+ """
+ if debug:
print(self.status)
print(self.reason)
print(self.body)
-#!/usr/bin/python
+# Copyright (C) 2017 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/.
-# This is PYTHON 2.x version of HTTP connection establishment
-
-from kea_conn import CARequest, CAResponse
+"""
+This is PYTHON 2.x version of HTTP connection establishment
+"""
import httplib
-class KeaConnector:
- def sendCA(self, params):
- # Estalbish HTTP connection first.
- conn = httplib.HTTPConnection(params.http_host, params.http_port)
- conn.connect()
+from kea_conn import CAResponse # CARequest
+
+def send_to_control_agent(params):
+ """Establish HTTP connection first."""
+ conn = httplib.HTTPConnection(params.http_host, params.http_port)
+ conn.connect()
- # Use POST to send it
- request = conn.putrequest('POST', params.path)
+ # Use POST to send it
+ _ = conn.putrequest('POST', params.path)
- # Send the headers first
- for k in params.headers:
- conn.putheader(k, params.headers[k])
- conn.endheaders()
+ # Send the headers first
+ for k in params.headers:
+ conn.putheader(k, params.headers[k])
+ conn.endheaders()
- # Send the content
- conn.send(params.content)
+ # Send the content
+ conn.send(params.content)
- # Now get the response
- resp = conn.getresponse()
+ # Now get the response
+ resp = conn.getresponse()
- # Now get the response details, put it in CAResponse and
- # return it
- x = CAResponse(resp.status, resp.reason, resp.read())
- conn.close()
+ # Now get the response details, put it in CAResponse and
+ # return it
+ result = CAResponse(resp.status, resp.reason, resp.read())
+ conn.close()
- return (x)
+ return result
-#!/usr/bin/python
+# Copyright (C) 2017 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/.
-from kea_conn import CARequest, CAResponse
+"""
+This is PYTHON 3.x version of HTTP connection establishment
+"""
import urllib.request
-class KeaConnector:
- def sendCA(self, params):
- # Estalbish HTTP connection first.
- url = "http://" + params.http_host + ":" + str(params.http_port) + str(params.path)
-
- req = urllib.request.Request(url = url, data = str.encode(params.content),
- headers = params.headers)
- resp = urllib.request.urlopen(req)
+from kea_conn import CAResponse # CARequest
- # Now get the response details, put it in CAResponse and
- # return it
- x = CAResponse(resp.getcode(), resp.reason, resp.read().decode("utf-8"))
+def send_to_control_agent(params):
+ """Establish HTTP connection first."""
+ url = "http://" + params.http_host + ":"
+ url += str(params.http_port) + str(params.path)
- return (x)
+ req = urllib.request.Request(url=url,
+ data=str.encode(params.content),
+ headers=params.headers)
+ resp = urllib.request.urlopen(req)
+
+ # Now get the response details, put it in CAResponse and return it
+ result = CAResponse(resp.getcode(), resp.reason,
+ resp.read().decode("utf-8"))
+
+ return result
}"
# In these tests we need to use two binaries: Control Agent and Kea shell.
-# Using bin and bin_path would be confusing, so we omit defining bin and bin_path
-# on purpose.
+# Using bin and bin_path would be confusing, so we omit defining bin
+# and bin_path on purpose.
ca_bin="kea-ctrl-agent"
ca_bin_path=@abs_top_builddir@/src/bin/agent
# of configuration failure).
get_pid ${ca_bin}
if [ ${_GET_PIDS_NUM} -ne 1 ]; then
- printf "ERROR: expected one Control Agent process to be started. Found %d processes\
- started.\n" ${_GET_PIDS_NUM}
+ printf "ERROR: expected one Control Agent process to be started.\
+ Found %d processes started.\n" ${_GET_PIDS_NUM}
clean_exit 1
fi
# It should be just once on startup.
get_reconfigs
if [ ${_GET_RECONFIGS} -ne 1 ]; then
- printf "ERROR: server been configured ${_GET_RECONFIGS} time(s), but exactly 1 was expected.\n"
+ printf "ERROR: server been configured ${_GET_RECONFIGS} time(s),\
+ but exactly 1 was expected.\n"
clean_exit 1
else
printf "Server successfully configured.\n"
fi
# Main test phase: send command, check response.
- tmp="echo \"${params}\" | ${shell_bin_path}/${shell_bin} --host 127.0.0.1 --port 8081 ${cmd} > ${tmpfile_path}/shell-stdout.txt"
+ tmp="echo \"${params}\" | ${shell_bin_path}/${shell_bin} --host \
+ 127.0.0.1 --port 8081 ${cmd} > ${tmpfile_path}/shell-stdout.txt"
echo "Executing kea-shell ($tmp)"
- echo "${params}" | ${shell_bin_path}/${shell_bin} --host 127.0.0.1 --port 8081 ${cmd} > ${tmpfile_path}/shell-stdout.txt
+ echo "${params}" | ${shell_bin_path}/${shell_bin} --host 127.0.0.1 \
+ --port 8081 ${cmd} > ${tmpfile_path}/shell-stdout.txt
# Check the exit code
shell_exit_code=$?
if [ ${shell_exit_code} -ne 0 ]; then
- echo "ERROR: kea-shell returned ${shell_exit_code} exit code, expected 0."
+ echo "ERROR:" \
+ "kea-shell returned ${shell_exit_code} exit code, expected 0."
else
echo "kea-shell returned ${shell_exit_code} exit code as expected."
fi
diff ${tmpfile_path}/shell-stdout.txt ${tmpfile_path}/shell-expected.txt
diff_code=$?
if [ ${diff_code} -ne 0 ]; then
- echo "ERROR: content returned is different than expected. See ${tmpfile_path}/shell-*.txt"
+ echo "ERROR:" \
+ "content returned is different than expected." \
+ "See ${tmpfile_path}/shell-*.txt"
echo "EXPECTED:"
cat ${tmpfile_path}/shell-expected.txt
echo "ACTUAL RESULT:"
if test "${REPORTED_VERSION}" == "${EXPECTED_VERSION}"; then
test_finish 0
else
- printf "ERROR: Expected version ${EXPECTED_VERSION}, got ${REPORTED_VERSION}\n"
+ echo "ERROR:" \
+ "Expected version ${EXPECTED_VERSION}, got ${REPORTED_VERSION}"
test_finish 1
fi
}
"[ { \"arguments\": [ \"list-commands\" ], \"result\": 0 } ]" ""
shell_command_test "shell.bogus" "give-me-a-beer" \
"[ { \"result\": 1, \"text\": \"'give-me-a-beer' command not supported.\" } ]" ""
-
-
+++ /dev/null
-# Copyright (C) 2017 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/.
-
-import unittest
-
-from kea_conn import CARequest
-
-class CARequestUnitTest(unittest.TestCase):
- """
- This class is dedicated to testing CARequest class. That class
- is responsible for generation of the body and headers.
- """
-
- def setUp(self):
- """
- This method is called before each test. Currently it does nothing.
- """
- pass
-
- def test_bodyWithoutParams(self):
- """
- This test verifies if the CARequest object generates the request
- content properly when there are no parameters.
- """
-
- x = CARequest()
- x.command = "foo"
- x.generateBody()
- self.assertEqual(x.content, '{ "command": "foo" }')
-
- def test_bodyWithParams(self):
- """
- This test verifies if the CARequest object generates the request
- content properly when there are parameters.
- """
-
- x = CARequest()
- x.command = "foo"
- x.params = '"bar": "baz"'
- x.generateBody()
- self.assertEqual(x.content, '{ "command": "foo", "parameters": { "bar": "baz" } }')
-
- def checkHeader(self, headers, header_name, value):
- """
- Checks if headers array contains an entry specified by header_name and that
- its value matches specified value
- """
-
- if header_name in headers:
- if (headers[header_name] == value):
- return True
- else:
- print ("Expected value: " + value + " does not match actual value: "
- + headers[header_name])
- return ()
- else:
- print ("Expected header: " + header_name + " missing")
- return (false)
-
- def test_headers(self):
- """
- This test checks if the headers are generated properly. Note that since
- the content is not specified, it is 0. Therefore Content-Length is 0.
- """
- x = CARequest()
- x.generateHeaders()
-
- self.assertTrue(self.checkHeader(x.headers, 'Content-Type', 'application/json'))
- self.assertTrue(self.checkHeader(x.headers, 'Accept', '*/*'))
- self.assertTrue(self.checkHeader(x.headers, 'Content-Length', "0"))
-
- def test_headerLength(self):
- """
- This test checks if the headers are generated properly. In this test there
- is specific content of non-zero length, and its size should be reflected
- in the header.
- """
- x = CARequest()
- x.content = '{ "command": "foo" }'
- x.generateHeaders()
-
- self.assertTrue(self.checkHeader(x.headers, 'Content-Length', str(len(x.content))))
-
- def test_headerVersion(self):
- """
- This test checks if the version reported in HTTP headers is generated properly.
- """
- x = CARequest()
- x.version = "1.2.3"
- x.generateHeaders()
- self.assertTrue(self.checkHeader(x.headers, 'User-Agent', 'Kea-shell/1.2.3'))
-
- def tearDown(self):
- """
- This method is called after each test. Currently it does nothing.
- """
- pass
-
-
-if __name__ == '__main__':
- unittest.main()
--- /dev/null
+#!@PYTHON@
+
+# Copyright (C) 2017 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/.
+
+"""
+Kea shell unittest (python part)
+"""
+
+import unittest
+
+from kea_conn import CARequest
+
+class CARequestUnitTest(unittest.TestCase):
+ """
+ This class is dedicated to testing CARequest class. That class
+ is responsible for generation of the body and headers.
+ """
+
+ def setUp(self):
+ """
+ This method is called before each test. Currently it does nothing.
+ """
+ pass
+
+ def test_body_without_params(self):
+ """
+ This test verifies if the CARequest object generates the request
+ content properly when there are no parameters.
+ """
+ request = CARequest()
+ request.command = "foo"
+ request.generate_body()
+ self.assertEqual(request.content, '{ "command": "foo" }')
+
+ def test_body_with_params(self):
+ """
+ This test verifies if the CARequest object generates the request
+ content properly when there are parameters.
+ """
+ request = CARequest()
+ request.command = "foo"
+ request.params = '"bar": "baz"'
+ request.generate_body()
+ self.assertEqual(request.content,
+ '{ "command": "foo", "parameters": { "bar": "baz" } }')
+
+ @staticmethod
+ def check_header(headers, header_name, value):
+ """
+ Checks if headers array contains an entry specified by
+ header_name and that its value matches specified value
+ """
+ if header_name in headers:
+ if headers[header_name] == value:
+ return True
+ else:
+ print("Expected value: " + value +
+ " does not match actual value: " +
+ headers[header_name])
+ return False
+ else:
+ print("Expected header: " + header_name + " missing")
+ return False
+
+ def test_headers(self):
+ """
+ This test checks if the headers are generated properly. Note that since
+ the content is not specified, it is 0. Therefore Content-Length is 0.
+ """
+ request = CARequest()
+ request.generate_headers()
+
+ self.assertTrue(self.check_header(request.headers,
+ 'Content-Type', 'application/json'))
+ self.assertTrue(self.check_header(request.headers,
+ 'Accept', '*/*'))
+ self.assertTrue(self.check_header(request.headers,
+ 'Content-Length', '0'))
+
+ def test_header_length(self):
+ """
+ This test checks if the headers are generated properly. In
+ this test there is specific content of non-zero length, and
+ its size should be reflected in the header.
+ """
+ request = CARequest()
+ request.content = '{ "command": "foo" }'
+ request.generate_headers()
+
+ self.assertTrue(self.check_header(request.headers, 'Content-Length',
+ str(len(request.content))))
+
+ def test_header_version(self):
+ """
+ This test checks if the version reported in HTTP headers is
+ generated properly.
+ """
+ request = CARequest()
+ request.version = "1.2.3"
+ request.generate_headers()
+ self.assertTrue(self.check_header(request.headers, 'User-Agent',
+ 'Kea-shell/1.2.3'))
+
+ def tearDown(self):
+ """
+ This method is called after each test. Currently it does nothing.
+ """
+ pass
+
+if __name__ == '__main__':
+ unittest.main()