From fc5a6c3a5d3b97116851d598ec37a9096b1b0e7a Mon Sep 17 00:00:00 2001 From: Mikolaj Izdebski Date: Apr 14 2016 13:17:31 +0000 Subject: [test] Refactor test database initialization Faitout support is removed. Database presence is assumed by default, but DB tests can be disabled by setting env variable. Additional DB logging is enabled and other custom options are set. --- diff --git a/koschei.spec b/koschei.spec index 94eb985..cd43349 100644 --- a/koschei.spec +++ b/koschei.spec @@ -157,11 +157,12 @@ ln -s %{_bindir}/python %{buildroot}%{_libexecdir}/%{name}/koschei-resolver %if %{with tests} %check -DB=$PWD/test/db -pg_ctl -s -w -D $DB init -o "-A trust" -pg_ctl -s -w -D $DB start -o "-F -h '' -k $DB" -trap 'pg_ctl -s -w -D $DB stop -m immediate' 0 -TEST_WITH_POSTGRES=1 POSTGRES_HOST=$DB %{__python2} setup.py test +export PGDATA=$PWD/test/db +export PGHOST=$PGDATA +pg_ctl -s -w init -o "-A trust" +pg_ctl -s -w start -o "-F -h '' -k $PGDATA" +trap 'pg_ctl -s -w stop -m immediate' 0 +%{__python2} setup.py test %endif %pre common diff --git a/test/__init__.py b/test/__init__.py index 3c2b551..35f6116 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -1,60 +1,15 @@ from __future__ import print_function import os -import sys -import logging import platform -import sqlalchemy -import requests -from koschei import models from koschei.config import load_config, get_config -faitout_url = 'http://faitout.fedorainfracloud.org/' - testdir = os.path.dirname(os.path.realpath(__file__)) -use_faitout = os.environ.get('TEST_WITH_FAITOUT') -use_postgres = os.environ.get('TEST_WITH_POSTGRES') -postgres_host = os.environ.get('POSTGRES_HOST') - is_x86_64 = platform.machine() == 'x86_64' load_config(['{0}/../config.cfg.template'.format(testdir), '{0}/test_config.cfg'.format(testdir)]) config = get_config(None) - -if use_faitout: - req = requests.get(faitout_url + 'new') - if req.status_code != 200: - print("Cannot obtain new faitout connection (code={code}): {text}" - .format(code=req.status_code, text=req.text), file=sys.stderr) - sys.exit(1) - config['database_url'] = req.text -elif use_postgres: - testdb = 'koschei_testdb' - config['database_config']['drivername'] = 'postgres' - config['database_config']['database'] = testdb - if postgres_host: - config['database_config']['host'] = postgres_host - cfg = config['database_config'].copy() - cfg['database'] = 'postgres' - url = sqlalchemy.engine.url.URL(**cfg) - config['database_url'] = url - engine = sqlalchemy.create_engine(url, poolclass=sqlalchemy.pool.NullPool) - conn = engine.connect() - conn.execute("COMMIT") - conn.execute("DROP DATABASE IF EXISTS {0}".format(testdb)) - conn.execute("COMMIT") - conn.execute("CREATE DATABASE {0}".format(testdb)) - conn.close() - -if use_postgres or use_faitout: - models.Base.metadata.create_all(models.get_engine()) - - -def teardown(): - if use_faitout: - requests.get(faitout_url + 'drop/' + - config['database_url'].rsplit('/', 1)[1]) diff --git a/test/common.py b/test/common.py index 3914e21..cb0edce 100644 --- a/test/common.py +++ b/test/common.py @@ -1,12 +1,17 @@ +from __future__ import print_function + import os +import sys import unittest import shutil import json +import psycopg2 from mock import Mock -from test import use_postgres, use_faitout, testdir, is_x86_64 +from test import testdir, is_x86_64 from koschei import models as m +from . import config workdir = '.workdir' @@ -42,8 +47,36 @@ class AbstractTest(unittest.TestCase): return json.load(fo) -@unittest.skipUnless(use_postgres or use_faitout, "Requires postgres") class DBTest(AbstractTest): + POSTGRES_OPTS = { + # Enable faster, but unsafe operation. + # (COMMIT statements return before WAL is written to disk.) + 'synchronous_commit': 'off', + # Log all SQL statements. + 'log_statement': 'all', + # Use sequential scanning only when absolutely necessary. Also enable logging + # of statement execution plans. With these two options combined, logs can be + # searched for sequential scans to find missing indexes. + 'enable_seqscan': 'off', + 'debug_print_plan': 'on', + } + postgres_initialized = None + + @staticmethod + def init_postgres(): + print("Initializing test database...", file=sys.stderr) + dbname = config['database_config']['database'] + with psycopg2.connect(dbname='postgres') as conn: + conn.autocommit = True + with conn.cursor() as cur: + cur.execute("DROP DATABASE IF EXISTS {0}".format(dbname)) + cur.execute("CREATE DATABASE {0}".format(dbname)) + for option, value in DBTest.POSTGRES_OPTS.iteritems(): + cur.execute("ALTER DATABASE {0} SET {1} TO '{2}'".format(dbname, + option, + value)) + m.Base.metadata.create_all(m.get_engine()) + def __init__(self, *args, **kwargs): super(DBTest, self).__init__(*args, **kwargs) self.s = None @@ -51,7 +84,18 @@ class DBTest(AbstractTest): self.collection = m.Collection(name="foo", display_name="Foo", target_tag="tag", build_tag="build_tag", priority_coefficient=1.0) + @classmethod + def setUpClass(cls): + super(DBTest, cls).setUpClass() + if DBTest.postgres_initialized is None: + DBTest.postgres_initialized = False + if not os.environ.get('TEST_WITHOUT_POSTGRES'): + DBTest.init_postgres() + DBTest.postgres_initialized = True + def setUp(self): + if not DBTest.postgres_initialized: + self.skipTest("requires PostgreSQL") super(DBTest, self).setUp() tables = m.Base.metadata.tables conn = m.get_engine().connect() diff --git a/test/test_config.cfg b/test/test_config.cfg index c410360..bdf541c 100644 --- a/test/test_config.cfg +++ b/test/test_config.cfg @@ -2,7 +2,10 @@ # test config config = { "is_test": True, - "database_config": {}, + "database_config": { + "drivername": "postgres", + "database": "koschei_testdb", + }, "koji_config": { "server": "", "topurl": "koji.fake",