summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/list_tests.py35
-rw-r--r--tests/log.py101
-rw-r--r--tests/requirements.txt26
-rw-r--r--tests/test_jvpp.py160
4 files changed, 322 insertions, 0 deletions
diff --git a/tests/list_tests.py b/tests/list_tests.py
new file mode 100644
index 0000000..35c94b4
--- /dev/null
+++ b/tests/list_tests.py
@@ -0,0 +1,35 @@
+# Copyright (c) 2019 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+
+
+def main():
+ """Discovers unittests in current directory and prints them as list of tests.
+
+ Example:
+ Parse test function name 'test_vpp_acl_callback_api (test_jvpp.TestJVpp)' to test descriptor:
+ test_jvpp.TestJVpp.test_vpp_acl_callback_api
+
+ """
+ suite = unittest.TestLoader().discover("")
+ for root_test in suite:
+ tests = root_test._tests
+ for parent_test in tests:
+ for jvpp_test in parent_test._tests:
+ test_name = jvpp_test.__str__().split()
+ print(test_name[1][1:-1] + "." + test_name[0])
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/log.py b/tests/log.py
new file mode 100644
index 0000000..aaffa3f
--- /dev/null
+++ b/tests/log.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import os
+import logging
+
+""" @var formatting delimiter consisting of '=' characters """
+double_line_delim = '=' * 78
+""" @var formatting delimiter consisting of '-' characters """
+single_line_delim = '-' * 78
+
+
+def colorize(msg, color):
+ return color + msg + COLOR_RESET
+
+
+class ColorFormatter(logging.Formatter):
+
+ def init(self, fmt=None, datefmt=None):
+ super(ColorFormatter, self).__init__(fmt, datefmt)
+
+ def format(self, record):
+ message = super(ColorFormatter, self).format(record)
+ if hasattr(record, 'color'):
+ message = colorize(message, record.color)
+ return message
+
+
+try:
+ verbose = int(os.getenv("V", 0))
+except:
+ verbose = 0
+
+# 40 = ERROR, 30 = WARNING, 20 = INFO, 10 = DEBUG, 0 = NOTSET (all messages)
+if verbose >= 2:
+ log_level = 10
+elif verbose == 1:
+ log_level = 20
+else:
+ log_level = 40
+
+handler = logging.StreamHandler(sys.stdout)
+color_formatter = ColorFormatter(fmt='%(asctime)s,%(msecs)03d %(message)s',
+ datefmt="%H:%M:%S")
+handler.setFormatter(color_formatter)
+handler.setLevel(log_level)
+
+global_logger = logging.getLogger()
+global_logger.addHandler(handler)
+
+scapy_logger = logging.getLogger("scapy.runtime")
+scapy_logger.setLevel(logging.ERROR)
+
+
+def get_logger(name):
+ logger = logging.getLogger(name)
+ logger.setLevel(logging.DEBUG)
+ return logger
+
+
+def get_parallel_logger(stream):
+ logger = logging.getLogger('parallel_logger_{}'.format(stream))
+ logger.propagate = False
+ logger.setLevel(logging.DEBUG)
+ handler = logging.StreamHandler(stream)
+ handler.setFormatter(color_formatter)
+ handler.setLevel(log_level)
+ logger.addHandler(handler)
+ return logger
+
+
+# Static variables to store color formatting strings.
+#
+# These variables (RED, GREEN, YELLOW and LPURPLE) are used to configure
+# the color of the text to be printed in the terminal. Variable COLOR_RESET
+# is used to revert the text color to the default one.
+if hasattr(sys.stdout, 'isatty') and sys.stdout.isatty():
+ RED = '\033[91m'
+ GREEN = '\033[92m'
+ YELLOW = '\033[93m'
+ LPURPLE = '\033[94m'
+ COLOR_RESET = '\033[0m'
+else:
+ RED = ''
+ GREEN = ''
+ YELLOW = ''
+ LPURPLE = ''
+ COLOR_RESET = ''
diff --git a/tests/requirements.txt b/tests/requirements.txt
new file mode 100644
index 0000000..2b15d01
--- /dev/null
+++ b/tests/requirements.txt
@@ -0,0 +1,26 @@
+# Copyright (c) 2019 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cffi # MIT
+cryptography!=2.0 # BSD/Apache-2.0
+faulthandler; python_version < '3.3' # # BSD License (2 clause)
+flake8 # MIT
+ipaddress; python_version < '3.3' # PSF
+parameterized>=0.6.1 # BSD
+pexpect # ISC
+psutil # BSD
+pycodestyle # MIT (Expat license) https://pypi.org/project/pycodestyle/
+scapy==2.4.0; python_version >= '2.7' or python_version >= '3.4' # GPL2 https://github.com/secdev/scapy/blob/master/LICENSE
+six # MIT
+subprocess32 # PSF
+syslog_rfc5424_parser>=0.3.0 # ISC
diff --git a/tests/test_jvpp.py b/tests/test_jvpp.py
new file mode 100644
index 0000000..862b285
--- /dev/null
+++ b/tests/test_jvpp.py
@@ -0,0 +1,160 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2019 Cisco and/or its affiliates.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import subprocess
+import unittest
+from log import get_logger
+
+API_FILES_PATH = "java/"
+
+# Registry jar file name prefix
+REGISTRY_JAR_PREFIX = "jvpp-registry"
+
+
+class TestJVpp(unittest.TestCase):
+ """ JVPP Core Test Case """
+
+ def invoke_for_jvpp_core(self, api_jar_name, test_class_name):
+ self.jvpp_connection_test(api_jar_name=api_jar_name,
+ test_class_name=test_class_name)
+
+ def test_vpp_core_callback_api(self):
+ """ JVPP Core Callback Api Test Case """
+ self.invoke_for_jvpp_core(api_jar_name="jvpp-core",
+ test_class_name="io.fd.jvpp.core.test."
+ "CallbackApiTest")
+
+ def test_vpp_registry_callback_api(self):
+ """ JVPP Core Callback Api Test Case """
+ self.invoke_for_jvpp_core(api_jar_name="jvpp-registry",
+ test_class_name="io.fd.jvpp.test."
+ "ConnectionTest")
+
+ def test_vpp_core_future_api(self):
+ """JVPP Core Future Api Test Case"""
+ self.invoke_for_jvpp_core(api_jar_name="jvpp-core",
+ test_class_name="io.fd.jvpp.core.test."
+ "FutureApiTest")
+
+ def test_vpp_acl_callback_api(self):
+ """ JVPP Acl Callback Api Test Case """
+ self.invoke_for_jvpp_core(api_jar_name="jvpp-acl",
+ test_class_name="io.fd.jvpp.acl.test."
+ "CallbackApiTest")
+
+ def test_vpp_acl_future_api(self):
+ """JVPP Acl Future Api Test Case"""
+ self.invoke_for_jvpp_core(api_jar_name="jvpp-acl",
+ test_class_name="io.fd.jvpp.acl.test."
+ "FutureApiTest")
+
+ def test_vpp_ioamexport_callback_api(self):
+ """ JVPP Ioamexport Callback Api Test Case """
+ self.invoke_for_jvpp_core(api_jar_name="jvpp-ioamexport",
+ test_class_name="io.fd.jvpp.ioamexport."
+ "test.CallbackApiTest")
+
+ def test_vpp_ioamexport_future_api(self):
+ """JVPP Ioamexport Future Api Test Case"""
+ self.invoke_for_jvpp_core(api_jar_name="jvpp-ioamexport",
+ test_class_name="io.fd.jvpp.ioamexport."
+ "test.FutureApiTest")
+
+ def test_vpp_ioampot_callback_api(self):
+ """ JVPP Ioampot Callback Api Test Case """
+ self.invoke_for_jvpp_core(api_jar_name="jvpp-ioampot",
+ test_class_name="io.fd.jvpp.ioampot."
+ "test.CallbackApiTest")
+
+ def test_vpp_ioampot_future_api(self):
+ """JVPP Ioampot Future Api Test Case"""
+ self.invoke_for_jvpp_core(api_jar_name="jvpp-ioampot",
+ test_class_name="io.fd.jvpp.ioampot."
+ "test.FutureApiTest")
+
+ def test_vpp_ioamtrace_callback_api(self):
+ """ JVPP Ioamtrace Callback Api Test Case """
+ self.invoke_for_jvpp_core(api_jar_name="jvpp-ioamtrace",
+ test_class_name="io.fd.jvpp.ioamtrace."
+ "test.CallbackApiTest")
+
+ def test_vpp_ioamtrace_future_api(self):
+ """JVPP Ioamtrace Future Api Test Case"""
+ self.invoke_for_jvpp_core(api_jar_name="jvpp-ioamtrace",
+ test_class_name="io.fd.jvpp.ioamtrace."
+ "test.FutureApiTest")
+
+ def test_vpp_snat_callback_api(self):
+ """ JVPP Snat Callback Api Test Case """
+ self.invoke_for_jvpp_core(api_jar_name="jvpp-nat",
+ test_class_name="io.fd.jvpp.nat.test."
+ "CallbackApiTest")
+
+ def test_vpp_snat_future_api(self):
+ """JVPP Snat Future Api Test Case"""
+ self.invoke_for_jvpp_core(api_jar_name="jvpp-nat",
+ test_class_name="io.fd.jvpp.nat.test."
+ "FutureApiTest")
+
+ @staticmethod
+ def full_jar_name(install_dir, jar_name, version):
+ return os.path.join(install_dir, API_FILES_PATH,
+ "{0}-{1}.jar".format(jar_name, version))
+
+ def jvpp_connection_test(self, api_jar_name, test_class_name):
+ self.logger = get_logger(api_jar_name)
+ install_dir = os.path.abspath('..')
+ self.logger.info("Install directory : {0}".format(install_dir))
+ self.shm_prefix = "honeycomb"
+ proc = subprocess.Popen(['../version'], stdout=subprocess.PIPE)
+ version = proc.stdout.read().split("-")[0]
+ registry_jar_path = self.full_jar_name(install_dir, REGISTRY_JAR_PREFIX, version)
+ self.logger.info("JVpp Registry jar path : {0}".format(registry_jar_path))
+ if not os.path.isfile(registry_jar_path):
+ raise Exception(
+ "JVpp Registry jar has not been found: {0}"
+ .format(registry_jar_path))
+
+ api_jar_path = self.full_jar_name(install_dir, api_jar_name, version)
+ self.logger.info("Api jar path : {0}".format(api_jar_path))
+ if not os.path.isfile(api_jar_path):
+ raise Exception(
+ "Api jar has not been found: {0}".format(api_jar_path))
+
+ # passes shm prefix as parameter to create connection with same value
+ command = ["sudo", "java", "-cp",
+ "{0}:{1}".format(registry_jar_path, api_jar_path),
+ test_class_name, "/vpe-api"]
+
+ self.process = subprocess.Popen(command, shell=False,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, bufsize=1,
+ universal_newlines=True)
+
+ out, err = self.process.communicate()
+ self.logger.info("Process output : {0}{1}".format(os.linesep, out))
+
+ if self.process.returncode != 0:
+ raise subprocess.CalledProcessError(self.process.returncode, command,
+ "Command {0} failed with return code: {1}.{2}"
+ "Process error output: {2}{3}"
+ .format(command, self.process.returncode, os.linesep, err))
+
+ def tearDown(self):
+ self.logger.info("Tearing down jvpp test")
+ super(TestJVpp, self).tearDown()
+ if hasattr(self, 'process') and self.process.poll() is None:
+ self.process.kill()