diff --git a/.gitattributes b/.gitattributes index 5a3b4c9131a9a006e51c12c6b48472af93b4abb0..88ae44cd946466acd7cc4f99df6130d58a7fb342 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1848,6 +1848,9 @@ LCU/Maintenance/DBInterface/monitoringdb/views/rtsm_views.py -text LCU/Maintenance/DBInterface/monitoringdb/views/station_test_views.py -text LCU/Maintenance/DBInterface/test/CMakeLists.txt -text LCU/Maintenance/DBInterface/test/__init__.py -text +LCU/Maintenance/DBInterface/test/postgres_testrunner.py -text +LCU/Maintenance/DBInterface/test/t_rtsm_models.run -text +LCU/Maintenance/DBInterface/test/t_rtsm_models.sh -text LCU/Maintenance/DBInterface/test/test_rtsm_models.py -text LCU/Maintenance/MDB_WebView/CMakeLists.txt -text LCU/Maintenance/MDB_WebView/maintenancedb_view/CMakeLists.txt -text diff --git a/LCU/Maintenance/DBInterface/test/CMakeLists.txt b/LCU/Maintenance/DBInterface/test/CMakeLists.txt index bf640677addcd6e0fe1623935a532fb602f0acf2..ad09e46b94647df94f38e44774a9640a4cf27937 100644 --- a/LCU/Maintenance/DBInterface/test/CMakeLists.txt +++ b/LCU/Maintenance/DBInterface/test/CMakeLists.txt @@ -1,7 +1,9 @@ # $Id$ -add_django_project_test_dir(mdb mdb DB_USER dino) +include(LofarCTest) set(py_files postgres_testrunner.py __init__.py test_rtsm_models.py) -python_install(${py_files} DESTINATION lofar/maintenance/test) \ No newline at end of file +python_install(${py_files} DESTINATION lofar/maintenance/test) + +lofar_add_test(t_rtsm_models) diff --git a/LCU/Maintenance/DBInterface/test/postgres_testrunner.py b/LCU/Maintenance/DBInterface/test/postgres_testrunner.py new file mode 100755 index 0000000000000000000000000000000000000000..279a431aea66faefa4815ba330c874860897b975 --- /dev/null +++ b/LCU/Maintenance/DBInterface/test/postgres_testrunner.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 + +""" +This allows running Django tests using a temporary postgres db (set up by tesing.postgresql) instead of using the +stock config in settings.py. Run as script to start postgres instance, returns PID to allow stopping it after use. + +To use this in Django tests, run: '.../manage.py test lsmrapp --testrunner=postgres_testrunner.PostgresqlTestRunner' +""" + +import testing.postgresql +from django.test.runner import DiscoverRunner +import psycopg2 +import signal +from django.conf import settings + +import logging +logger = logging.getLogger(__name__) + +# todo: consider switching from testing.postgresql to pyembedpg to allow easy testing on specific versions. That may be slower, though. + +try: + import testing.postgresql +except ImportError as e: + print(str(e)) + print('Please install python package testing.postgresql: sudo pip3 install testing.postgresql') + exit(3) # special lofar test exit code: skipped test + +def execute_query(pg, query): + """ + Run a raw SQL query on the given database + :param pg: A testing.postgresql.Postgresql instance + :param query: The query to execute + """ + + # connect to Postgres as root + connection = psycopg2.connect(**pg.dsn()) + connection.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) + cursor = connection.cursor() + + # create user role + cursor.execute(query) + cursor.close() + connection.commit() + connection.close() + + +def create_admin_role(pg, user, passw): + """ + Adds a superuser to the provided Postgres instance + :param pg: A testing.postgresql.Postgresql instance + :return: + """ + query = "CREATE ROLE %s WITH SUPERUSER LOGIN PASSWORD '%s';" % (user, passw) + try: + execute_query(pg, query) + except Exception as e: + logger.error(e) + + +def create_project_db(pg, name): + """ + Creates a new database in the provided Postgres instance + :param pg: A testing.postgresql.Postgresql instance + :param name: The name of the database to create + """ + name = settings.DATABASES['default']['NAME'] + query = "CREATE DATABASE %s;" % (name) + execute_query(pg, query) + + +def create_test_postgres(host, port, user, passw): + """ + Fires up a non-persistent Postgresql database with superuser for the provided details + :return: A testing.postgresql.Postgresql instance + """ + postgresql = testing.postgresql.Postgresql(host=host, port=port) + logger.debug('creating test database instance at host %s and port %s', host, port) + create_admin_role(postgresql, user, passw) + return postgresql + + +def create_test_Postgres_from_django_settings(): + """ + Reads default connection details from settings.py and creates an according Postgres instance + :return: A testing.postgresql.Postgresql instance + """ + host = settings.DATABASES['default']['HOST'] + port = settings.DATABASES['default']['PORT'] + user = settings.DATABASES['default']['USER'] + passw = settings.DATABASES['default']['PASS'] + return create_test_postgres(host, port, user, passw) + + +class PostgresqlTestRunner(DiscoverRunner): + """ + A test runner to pass to manage.py test to start and tear down a database for testing. + Uses the connection details as configured in settings.py + """ + + def setup_databases(self, **kwargs): + self.postgresql = create_test_Postgres_from_django_settings() + logger.info('created test postgres instance based on Django settings') + return super(PostgresqlTestRunner, self).setup_databases(**kwargs) + + def teardown_databases(self, old_config, **kwargs): + self.postgresql.stop() + +# raise normal Exception when a signal is caught so can allow postgresql to stop +class SigTermException(Exception): + pass + +def signal_handler(_s,_f): + raise SigTermException("signal %s received..." % (_s,)) + +for s in [signal.SIGHUP, signal.SIGTERM, signal.SIGINT]: + signal.signal(s, signal_handler) diff --git a/LCU/Maintenance/DBInterface/test/t_rtsm_models.run b/LCU/Maintenance/DBInterface/test/t_rtsm_models.run new file mode 100755 index 0000000000000000000000000000000000000000..54eb4cbfe7c4cf0b05378c25a5a4b6c26f8416d5 --- /dev/null +++ b/LCU/Maintenance/DBInterface/test/t_rtsm_models.run @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +python3 -m lofar.maintenance.manage test lofar.maintenance.test.test_rtsm_models --testrunner=lofar.maintenance.test.postgres_testrunner.PostgresqlTestRunner --settings lofar.maintenance.django_postgresql.test_settings diff --git a/LCU/Maintenance/DBInterface/test/t_rtsm_models.sh b/LCU/Maintenance/DBInterface/test/t_rtsm_models.sh new file mode 100755 index 0000000000000000000000000000000000000000..4b6a59dbc61807b9c3688d4dd65756b256b6e7f0 --- /dev/null +++ b/LCU/Maintenance/DBInterface/test/t_rtsm_models.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +./runctest.sh t_rtsm_models \ No newline at end of file