diff --git a/lib/features/admin.feature b/lib/features/admin.feature index 6183fb2..3d1af44 100644 --- a/lib/features/admin.feature +++ b/lib/features/admin.feature @@ -1,9 +1,18 @@ -# Created by nicklasborjesson at 30/05/16 +# Created by nibo at 2015-06-03 Feature: Administrative functions and interface The admin web backend is basically just a web facing API frontend, broker restarting and similar features are actually tested in the broker library implementation instead. Here, mostly UI-supporting functionality is tested - Scenario: Generate initialisation file - Given several plugins have loaded - And refresh_init has been run - Then admin_ui_init should be properly structured \ No newline at end of file + + Scenario: Starting broker and use the API to shut everything down + Given the broker is started + And we wait 2 seconds + And it is it possible to register an admin at the broker + And the broker is told to restart using the API + And we wait 4 seconds + And it is it possible to register an admin at the broker + And the broker is told to stop using the API + And we wait 2 seconds + And a get environment request should fail + +""" \ No newline at end of file diff --git a/lib/features/environment.py b/lib/features/environment.py index 603803d..d0cba9d 100644 --- a/lib/features/environment.py +++ b/lib/features/environment.py @@ -2,11 +2,14 @@ Initialization for OF broker tests. """ import os -from admin.lib.admin import CherryPyAdmin -__author__ = 'Nicklas Borjesson' +from of.broker.testing.init_env import init_env +__author__ = 'Nicklas Borjesson' +# Test users uuids +id_user_root = "000000010000010001e64c30" +id_user_test = "000000010000010001e64c31" id_right_admin_nodes = "000000010000010001e64d01" @@ -14,9 +17,10 @@ script_dir = os.path.dirname(__file__) def before_all(context): - _plugins = - context.admin = CherryPyAdmin(_address="test", _plugins=) + os.environ["OPTIMAL_FW_CFG"] = os.path.join(script_dir, "steps", "config.json") + init_env(_database_name = "test_admin", _context = context) + def init_broker_cycles(context, feature): print("\nRunning Broker startup and shutdown scenarios\n=========================================================\n") diff --git a/lib/features/steps/admin.py b/lib/features/steps/admin.py new file mode 100644 index 0000000..48f3d4a --- /dev/null +++ b/lib/features/steps/admin.py @@ -0,0 +1,162 @@ +import os + +import traceback +from multiprocessing import Process +import time + +from behave import * +from nose.tools.trivial import ok_ + +from of.broker.features import run_broker_testing +from of.common.messaging.utils import call_api, register_at_broker + +use_step_matcher("re") + +_log_prefix = "Tester - Broker Cycles :" +script_dir = os.path.dirname(__file__) + + + +@given("the broker is started") +def step_impl(context): + """ + :type context behave.runner.Context + """ + try: + print(_log_prefix + "Starting broker process.") + context.broker_process = Process(name="broker_testing", target=run_broker_testing, daemon=False) + context.broker_process.start() + if context.broker_process.exitcode: + ok_(False, "Failed starting the process, it terminated within wait time.") + else: + ok_(True) + except Exception as e: + print(_log_prefix + "Error starting broker: " + str(e) + "\nTraceback:" + traceback.format_exc()) + ok_(False) + + + + + +@then("a termination on linux should return zero as exit code") +def step_impl(context): + """ + :type context behave.runner.Context + """ + print(_log_prefix + "Terminating the broker process") + context.broker_process.terminate() + try: + context.broker_process.join(timeout=10) + except: + ok_(False, "Broker process did not exit within 5 seconds") + if os.name == "nt": + print("Terminations cannot be gracefully catched and acted upon on windows") + ok_(True) + else: + if context.broker_process.exitcode != 0: + ok_(False, "Broker process exited with a nonzero exit code: " + str(context.broker_process.exitcode)) + else: + ok_(True) + + +@step("the broker is told to restart using the API") +def step_impl(context): + """ + :type context behave.runner.Context + """ + print(_log_prefix + "Telling Broker to restart using a call to broker_control...") + call_api(_url="https://127.0.0.1:8080/admin/broker_control", + _session_id=context.session["session_id"], + _data={"command": "restart", "reason": "Testing restarting the broker"}, + _verify_SSL=False + ) + print(_log_prefix + "Waiting for process to exit...") + + context.broker_process.join(timeout=2) + ok_(True) + +@step("the broker is told to stop using the API") +def step_impl(context): + """ + :type context behave.runner.Context + """ + print(_log_prefix + "Telling Broker to stop using a call to stop_broker...") + call_api(_url="https://127.0.0.1:8080/admin/broker_control", + _session_id=context.session["session_id"], + _data={"command": "stop", "reason": "Testing stopping the broker"}, + _verify_SSL=False + ) + ok_(True) + +@step("a get environment request should fail") +def step_impl(context): + """ + :type context behave.runner.Context + """ + try: + _response = call_api(_url="https://127.0.0.1:8080/get_broker_environment", + _session_id=context.session["session_id"], + _data={}, _verify_SSL=False) + except Exception as e: + ok_(True, str(e)) + else: + + os.kill(_response["systemPid"], 9) + ok_(False, "The broker could still be reached after being told to shut down, killed pid "+ str(_response["systemPid"] + " manually.")) + + +@step("we wait (?P.+) seconds") +def step_impl(context, seconds): + """ + :type context behave.runner.Context + """ + time.sleep(float(seconds)) + ok_(True) + + +@step("there is a web_socket peer with the address (?P
.+)") +def step_impl(context, address): + """ + :type context behave.runner.Context + """ + print("Tester: Calling get_peers and checking for the address " + str(address)) + try: + _peers = call_api(_url="https://127.0.0.1:8080/admin/get_peers", + _session_id=context.session["session_id"], + _data={}, _verify_SSL=False + ) + except Exception as e: + ok_(False, "An error occurred contacting server:" + str(e)) + if _peers: + for _peer in _peers: + + if "web_socket" in _peer and _peer["address"] == address and _peer["web_socket"] == "removed for serialization": + ok_(True) + return + ok_(False, "No " + str(address) + " peer registered.") + else: + ok_(False, "No response from the server.") + + + +@step("it is it possible to register an (?P.+) at the broker") +def step_impl(context, peer_type): + """ + :type context behave.runner.Context + """ + + try: + context.session = register_at_broker(_address="test", _type=peer_type, _server="https://127.0.0.1:8080", + _username="tester", _password="test", _verify_SSL=False) + + if context.session["session_id"]: + print("Successfully registered at broker, got sessionid: " + str(context.session["session_id"])) + ok_(True) + else: + ok_(False, "No session Id returned.") + except ConnectionError as e: + ok_(False, "'Connection Error registering:" + str(e)) + except Exception as e: + ok_(False, "Error registering:" + str(e)) + + diff --git a/lib/features/steps/config.json b/lib/features/steps/config.json new file mode 100644 index 0000000..d2c0908 --- /dev/null +++ b/lib/features/steps/config.json @@ -0,0 +1,14 @@ +{ + "broker": { + "address": "broker01", + "pluginFolder": "../../../../", + "packageNameOverride": "admin", + "database": { + "databaseName": "test_admin" + }, + "logging": { + "severityLevel": "debug", + "databaseLevel": "debug" + } + } +} diff --git a/lib/features/steps/optimalframework_test_cert.pem b/lib/features/steps/optimalframework_test_cert.pem new file mode 100644 index 0000000..3c37093 --- /dev/null +++ b/lib/features/steps/optimalframework_test_cert.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDzzCCAregAwIBAgIJAMdpiQTFggwPMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV +BAYTAlNFMRIwEAYDVQQIDAlTdG9ja2hvbG0xEjAQBgNVBAcMCVN0b2NraG9sbTEU +MBIGA1UECgwLT3B0aW1hbCBCUE0xCzAJBgNVBAsMAklUMSQwIgYJKoZIhvcNAQkB +FhVuaWNrbGFzQG9wdGltYWxicG0uc2UwHhcNMTQxMDEwMDgzMjA2WhcNMTUxMDEw +MDgzMjA2WjB+MQswCQYDVQQGEwJTRTESMBAGA1UECAwJU3RvY2tob2xtMRIwEAYD +VQQHDAlTdG9ja2hvbG0xFDASBgNVBAoMC09wdGltYWwgQlBNMQswCQYDVQQLDAJJ +VDEkMCIGCSqGSIb3DQEJARYVbmlja2xhc0BvcHRpbWFsYnBtLnNlMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8XbKuUcoxhlX4c37T+gY7vnIdjRKgoUk +YeoGVmrO9DMjwIJPYNbDdL/QdB2mrfEb7neKiWPSGEESJixr4qPq0VmMqob7Eea2 +tC8gURp7pfofDXsdHWYXF/ExsOCk7zrdNnm3TeGes1tKytzTEDjag6IRmPklfEXq +NESwUlvelQP2GDb9LEnmRedDNI/1mU9u/79hp9QY6oLsmYAhYtomxCxBCnj+XjX8 +Sy4SlZcFHtGeZbtaUB1404gUgv0wsVW2rX7RZ0lFnhKLNKKyeT+moDZ+NvfXgVTa +YuKaT9+UUVsi4KaigQbNLrvE+AX5zmBiRylDiHMVMGtPmg2Xdz1r4QIDAQABo1Aw +TjAdBgNVHQ4EFgQUVc2KyfuvSGybHaXUWs5YeAQxC3QwHwYDVR0jBBgwFoAUVc2K +yfuvSGybHaXUWs5YeAQxC3QwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC +AQEAp/ykY6bYUxnFdXeJMaTyl0GA07DgWiZHQucdLpZu4lqY2oCpnVKFgNj+klhb +5n5FkWEspHqN4Nadokz398FLXAsbxLtUTcdizVmO6PCg98rGrWDuT2dRAMvf7PJ8 +eteHV4NybSirc640Kv+Y9+E59I9LNSy+uXy1YnpukZyT6a+69zwGSjZ+J2mN9uaX +/738ENnId+9luCSk91yP5ZDKILscQPrw7C9GAxb+LYLRqH38/WWKJs4vT1QMkq9a +XTCjas3pcCRSiiseVx0oeLt4Y9zcgbVQrSDYR60pD2ho7xz3tvzRCLW0bEW16kd6 +Qoc8FkB8peEMJKrKSg/FPsOolw== +-----END CERTIFICATE----- diff --git a/lib/features/steps/optimalframework_test_privkey.pem b/lib/features/steps/optimalframework_test_privkey.pem new file mode 100644 index 0000000..49fd7b7 --- /dev/null +++ b/lib/features/steps/optimalframework_test_privkey.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA8XbKuUcoxhlX4c37T+gY7vnIdjRKgoUkYeoGVmrO9DMjwIJP +YNbDdL/QdB2mrfEb7neKiWPSGEESJixr4qPq0VmMqob7Eea2tC8gURp7pfofDXsd +HWYXF/ExsOCk7zrdNnm3TeGes1tKytzTEDjag6IRmPklfEXqNESwUlvelQP2GDb9 +LEnmRedDNI/1mU9u/79hp9QY6oLsmYAhYtomxCxBCnj+XjX8Sy4SlZcFHtGeZbta +UB1404gUgv0wsVW2rX7RZ0lFnhKLNKKyeT+moDZ+NvfXgVTaYuKaT9+UUVsi4Kai +gQbNLrvE+AX5zmBiRylDiHMVMGtPmg2Xdz1r4QIDAQABAoIBABxOo9dyqyoGIJJd +NoAYoouphsGswatpdmlwKQwKe3aPZDqWTD37D3DpZ8OlEjxEDtU2+GvA4wlq33jQ +Llmkg8vFJsN7DYX8uSCIgc5gP2ym1Oscqr4ekMiCwyOMQmm1Seev/zhHIfa+1hbQ +KoI1WBCkeFGpq6ZU/+7eupj9Iivvz6VVTrMd4dDJ4RcdnFpD+MWJ6FT4vNv2/ynD +LzvE2R3gGAjZgv9/tufHMW5beKq4ICYUhgm4CIeT5ODqAXtFmsnWumFPPP0hp1zs +EVrALtvJruLAkODOwVzgMwudHsPrPlDXeRSaAAEJaqOKkyaWcstTe3Q2kGJS3HAF ++JMJGE0CgYEA/O7x/96ri5hQQw8GsfXSDFzPRUVQebyqOV0OllE41E6/bPaFYHcu +y7Ey6fkPSw8teWSlR+P3pZj8chyJRstZqsrhwUow/Zw4Wj3BB9Hs6S0p4rZZfvP/ +mbFwtt+4Ka+VyfgLH1RaT7AiTHFfC0KFm6T05e2EmfSuRA1MHahfjm8CgYEA9GQ/ +fZKBbzbhNX4cjseyutoG8IoQI6MjiIcJQDMdRwn+TtT1QSvxr01f2H22Tsvw88iE +7Lql5m8k5IOcprciISmAgAkMedeUqyoDi04j3xIRrtjV779K2eEB705tpKQrbtSf +UEIyLzlQAqPd66zjbS0TDXrgd4ndzpPW4YAs0q8CgYEAuwLQ2yaAH86WSX6qrJnc +nFdiyQze26OrGI69Ylbbdd5jmuUK6LA2YVS7GFOWAyFNthu8ONNNH5tly9ldhoKD +4cvv70Izxs/iupY+StHkIOPLvFym/z7ZFYIknJH9UJUKYzKKxrdPruvD8FFCvMiK +kPH+QKLFEC/hSV+rj6IWRPECgYA5Y+k89dCLa1nLlAfkx6SDGHwUtHdBxyerAfr8 +JoSzj/c2T/AgE8+3mPXvAuZy7pVwyh/c75/R0zvYpcd9pvfOzc4tQvK5EhUJdN5M +MldeJQIeCzGCEWvkamBn8ATzatIAPtICqOjcChtt40lT9M+bbcBRpA9eQvPhdPo7 +Djx4ZQKBgQDglNfU+iGR4kbUlsi6jhgG9T4hehNKvxOY5jRdSBlehisbVzJ4XpKu +rNHPpZAF43XvKHA9OpWJUCI3QVj7qb2hLLBuRt+LdVr9J+Mm4l/tZ8mB6ulzlkZI +++yggRqAoHJ8SQ453H2m72mip0XY/JFhzKLTj4nsuakI4vXgjSgPLA== +-----END RSA PRIVATE KEY-----