summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2014-05-28 18:29:39 -0400
committerSimo Sorce <simo@redhat.com>2014-06-04 10:26:34 -0400
commit54aa265915f305f688051bebf940fcbe000ddce2 (patch)
tree264d97cd156097dfec011f44deca8d484ffefe3a /tests
parentdcca975c45427c0176e882f158f816af0336ea43 (diff)
downloadipsilon-54aa265915f305f688051bebf940fcbe000ddce2.tar.gz
ipsilon-54aa265915f305f688051bebf940fcbe000ddce2.tar.xz
ipsilon-54aa265915f305f688051bebf940fcbe000ddce2.zip
Add basic testing infrastructure
make test will now run some sanity tests to make sure basic installation procedures work in a sinthetic test environment. Adds: - custom httpd setup for tests - use profiles to driver ipsilon servers and clients installation - starts multiple httpd servers This way we can test interaction between IDP and SP servers Signed-off-by: Simo Sorce <simo@redhat.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/__init__.py0
-rw-r--r--tests/httpd.conf107
-rwxr-xr-xtests/tests.py244
3 files changed, 351 insertions, 0 deletions
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/__init__.py
diff --git a/tests/httpd.conf b/tests/httpd.conf
new file mode 100644
index 0000000..6b2a4cb
--- /dev/null
+++ b/tests/httpd.conf
@@ -0,0 +1,107 @@
+ServerRoot "${HTTPROOT}"
+Listen ${HTTPADDR}:${HTTPPORT}
+
+LoadModule access_compat_module modules/mod_access_compat.so
+LoadModule actions_module modules/mod_actions.so
+LoadModule alias_module modules/mod_alias.so
+LoadModule allowmethods_module modules/mod_allowmethods.so
+LoadModule auth_basic_module modules/mod_auth_basic.so
+#LoadModule auth_digest_module modules/mod_auth_digest.so
+LoadModule authn_anon_module modules/mod_authn_anon.so
+LoadModule authn_core_module modules/mod_authn_core.so
+LoadModule authn_dbd_module modules/mod_authn_dbd.so
+LoadModule authn_dbm_module modules/mod_authn_dbm.so
+LoadModule authn_file_module modules/mod_authn_file.so
+LoadModule authn_socache_module modules/mod_authn_socache.so
+LoadModule authz_core_module modules/mod_authz_core.so
+LoadModule authz_dbd_module modules/mod_authz_dbd.so
+LoadModule authz_dbm_module modules/mod_authz_dbm.so
+LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
+LoadModule authz_host_module modules/mod_authz_host.so
+LoadModule authz_owner_module modules/mod_authz_owner.so
+LoadModule authz_user_module modules/mod_authz_user.so
+LoadModule autoindex_module modules/mod_autoindex.so
+LoadModule cache_module modules/mod_cache.so
+LoadModule cache_disk_module modules/mod_cache_disk.so
+LoadModule data_module modules/mod_data.so
+LoadModule dbd_module modules/mod_dbd.so
+LoadModule deflate_module modules/mod_deflate.so
+LoadModule dir_module modules/mod_dir.so
+LoadModule dumpio_module modules/mod_dumpio.so
+LoadModule echo_module modules/mod_echo.so
+LoadModule env_module modules/mod_env.so
+LoadModule expires_module modules/mod_expires.so
+LoadModule ext_filter_module modules/mod_ext_filter.so
+LoadModule filter_module modules/mod_filter.so
+LoadModule headers_module modules/mod_headers.so
+LoadModule include_module modules/mod_include.so
+LoadModule info_module modules/mod_info.so
+LoadModule log_config_module modules/mod_log_config.so
+LoadModule logio_module modules/mod_logio.so
+LoadModule macro_module modules/mod_macro.so
+LoadModule mime_magic_module modules/mod_mime_magic.so
+LoadModule mime_module modules/mod_mime.so
+LoadModule negotiation_module modules/mod_negotiation.so
+LoadModule remoteip_module modules/mod_remoteip.so
+LoadModule reqtimeout_module modules/mod_reqtimeout.so
+LoadModule rewrite_module modules/mod_rewrite.so
+LoadModule setenvif_module modules/mod_setenvif.so
+LoadModule slotmem_plain_module modules/mod_slotmem_plain.so
+LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
+LoadModule socache_dbm_module modules/mod_socache_dbm.so
+LoadModule socache_memcache_module modules/mod_socache_memcache.so
+LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
+LoadModule status_module modules/mod_status.so
+LoadModule substitute_module modules/mod_substitute.so
+LoadModule suexec_module modules/mod_suexec.so
+LoadModule unique_id_module modules/mod_unique_id.so
+LoadModule unixd_module modules/mod_unixd.so
+LoadModule userdir_module modules/mod_userdir.so
+LoadModule version_module modules/mod_version.so
+LoadModule vhost_alias_module modules/mod_vhost_alias.so
+
+LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
+LoadModule wsgi_module modules/mod_wsgi.so
+LoadModule auth_mellon_module modules/mod_auth_mellon.so
+
+<Directory />
+ AllowOverride none
+ Require all denied
+</Directory>
+
+DocumentRoot "${HTTPROOT}/html"
+<Directory "${HTTPROOT}">
+ AllowOverride None
+ # Allow open access:
+ Require all granted
+</Directory>
+<Directory "${HTTPROOT}/html">
+ Options Indexes FollowSymLinks
+ AllowOverride None
+ Require all granted
+</Directory>
+
+<IfModule dir_module>
+ DirectoryIndex index.html
+</IfModule>
+
+<Files ".ht*">
+ Require all denied
+</Files>
+
+PidFile "${HTTPROOT}/logs/httpd.pid"
+
+ErrorLog "logs/error_log"
+LogLevel debug
+
+<IfModule mime_module>
+ TypesConfig /etc/mime.types
+ AddType application/x-compress .Z
+ AddType application/x-gzip .gz .tgz
+ AddType text/html .shtml
+ AddOutputFilter INCLUDES .shtml
+</IfModule>
+
+AddDefaultCharset UTF-8
+
+IncludeOptional conf.d/*.conf
diff --git a/tests/tests.py b/tests/tests.py
new file mode 100755
index 0000000..cfd63c6
--- /dev/null
+++ b/tests/tests.py
@@ -0,0 +1,244 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2014 Simo Sorce <simo@redhat.com>
+#
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import argparse
+import ConfigParser
+from datetime import datetime
+import logging
+import os
+import pwd
+import shutil
+import signal
+import subprocess
+import sys
+from string import Template
+
+
+logger = None
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(description='Ipsilon Tests Environment')
+ parser.add_argument('--path', default='%s/testdir' % os.getcwd(),
+ help="Directory in which tests are run")
+ parser.add_argument('--test', default='test1',
+ help="The test to run")
+
+ return vars(parser.parse_args())
+
+
+def openlogs(path, test):
+ global logger # pylint: disable=W0603
+ logger = logging.getLogger()
+ try:
+ datestr = datetime.now().strftime("%Y-%m-%d_%H:%M:%S")
+ filename = '%s/test-%s-%s.log' % (path, test, datestr)
+ lh = logging.FileHandler(filename)
+ except IOError, e:
+ print >> sys.stderr, 'Unable to open %s (%s)' % (filename, str(e))
+ lh = logging.StreamHandler(sys.stderr)
+ formatter = logging.Formatter('[%(asctime)s] %(message)s')
+ lh.setFormatter(formatter)
+ logger.addHandler(lh)
+ logger.setLevel(logging.DEBUG)
+
+
+def force_remove(op, name, info):
+ os.chmod(name, 0700)
+ os.remove(name)
+
+
+def setup_http(httpdir, addr, port):
+ os.mkdir(httpdir)
+ os.mkdir(httpdir + '/conf.d')
+ os.mkdir(httpdir + '/html')
+ os.mkdir(httpdir + '/logs')
+ os.symlink('/etc/httpd/modules', httpdir + '/modules')
+
+ with open('tests/httpd.conf') as f:
+ t = Template(f.read())
+ text = t.substitute({'HTTPROOT': httpdir,
+ 'HTTPADDR': addr, 'HTTPPORT': port})
+ with open(httpdir + '/httpd.conf', 'w+') as f:
+ f.write(text)
+
+
+def setup_test(path, test):
+ profile = 'tests/%s.cfg' % test
+ if not os.path.exists(profile):
+ raise ValueError('Unrecognized test name [%s]' % test)
+
+ opts = {}
+ config = ConfigParser.ConfigParser()
+ config.read(profile)
+ if 'tests' not in config.sections():
+ raise ValueError('Missing [tests] in profile [%s]' % test)
+ T = config.options('tests')
+ for t in T:
+ opts[t] = config.get('tests', t)
+
+ base = '%s/%s' % (path, test)
+ if os.path.exists(base):
+ shutil.rmtree(base, onerror=force_remove)
+ os.makedirs(base)
+ shutil.copytree('templates', base + '/templates')
+ os.mkdir(base + '/etc')
+ os.mkdir(base + '/lib')
+ os.mkdir(base + '/lib/' + test)
+ os.mkdir(base + '/log')
+
+ with open(profile) as f:
+ t = Template(f.read())
+ text = t.substitute({'TESTDIR': base, 'ROOTDIR': os.getcwd(),
+ 'TEST_USER': pwd.getpwuid(os.getuid())[0]})
+ with open(base + '/profile.cfg', 'w+') as f:
+ f.write(text)
+
+ opts['basedir'] = base
+ return opts
+
+
+def generate_profile(profile, name):
+ config = ConfigParser.ConfigParser()
+ config.read(profile)
+
+ global_section = '%s_globals' % name
+ global_options = {}
+ if global_section in config.sections():
+ G = config.options(global_section)
+ for g in G:
+ global_options[g] = config.get(global_section, g)
+
+ args_section = '%s_arguments' % name
+ args_options = {}
+ if args_section in config.sections():
+ A = config.options(args_section)
+ for a in A:
+ args_options[a] = config.get(args_section, a)
+
+ newconf = ConfigParser.ConfigParser()
+ newconf.add_section('globals')
+ for k in global_options.keys():
+ newconf.set('globals', k, global_options[k])
+ newconf.add_section('arguments')
+ for k in args_options.keys():
+ newconf.set('arguments', k, args_options[k])
+
+ filename = os.path.join(os.path.dirname(profile), '%s_profile.cfg' % name)
+ with open(filename, 'wb') as f:
+ newconf.write(f)
+
+ return filename
+
+
+def fixup_sp_httpd(httpdir):
+ location = """
+
+Alias /sp ${HTTPDIR}/sp
+
+<Directory ${HTTPDIR}/sp>
+ Require all granted
+</Directory>
+"""
+ index = """WORKS!"""
+
+ t = Template(location)
+ text = t.substitute({'HTTPDIR': httpdir})
+ with open(httpdir + '/conf.d/ipsilon-saml.conf', 'a') as f:
+ f.write(text)
+
+ os.mkdir(httpdir + '/sp')
+ with open(httpdir + '/sp/index.html', 'w') as f:
+ f.write(index)
+
+if __name__ == '__main__':
+
+ args = parse_args()
+
+ if not os.path.exists(args['path']):
+ os.makedirs(args['path'])
+ openlogs(args['path'], args['test'])
+
+ options = setup_test(args['path'], args['test'])
+ basedir = options['basedir']
+
+ env={'PYTHONPATH':'./'}
+ srvs = []
+ try:
+ for h in options['servers'].split(','):
+ sname, saddr, sport = h.split(':')
+ basehttpdir = '%s/%s' % (basedir, sname)
+ setup_http(basehttpdir, saddr, sport)
+
+ sprofile = generate_profile('%s/profile.cfg' % basedir, sname)
+ p = subprocess.Popen(['./ipsilon/install/ipsilon-server-install',
+ '--config-profile=%s' % sprofile], env=env,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, stderr = p.communicate()
+ logger.error(stderr)
+ logger.info(stdout)
+ if p.returncode:
+ sys.exit(p.returncode)
+
+ os.symlink('%s/ipsilon' % os.getcwd(),
+ '%s/lib/%s/ipsilon' % (basedir, sname))
+
+ print "Starting httpd server in %s" % basehttpdir
+ srv = subprocess.Popen(['/usr/sbin/httpd', '-DFOREGROUND',
+ '-f', basehttpdir + '/httpd.conf'],
+ env=env, preexec_fn=os.setsid)
+ srvs.append(srv)
+
+ for h in options['clients'].split(','):
+ sname, saddr, sport = h.split(':')
+ basehttpdir = '%s/%s' % (basedir, sname)
+ setup_http(basehttpdir, saddr, sport)
+
+ sprofile = generate_profile('%s/profile.cfg' % basedir, sname)
+ p = subprocess.Popen(['./ipsilon/install/ipsilon-client-install',
+ '--config-profile=%s' % sprofile], env=env,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, stderr = p.communicate()
+ logger.error(stderr)
+ logger.info(stdout)
+ if p.returncode:
+ sys.exit(p.returncode)
+
+ fixup_sp_httpd(basehttpdir)
+
+ print "Starting httpd server in %s" % basehttpdir
+ srv = subprocess.Popen(['/usr/sbin/httpd', '-DFOREGROUND',
+ '-f', basehttpdir + '/httpd.conf'],
+ env=env, preexec_fn=os.setsid)
+ srvs.append(srv)
+
+ if os.path.exists('tests/%s.py' % args['test']):
+ code = subprocess.call(['./tests/%s.py' % args['test'], basedir],
+ env=env)
+ if code:
+ sys.exit(code)
+ except Exception: # pylint: disable=broad-except
+ sys.exit(1)
+ finally:
+ for srv in srvs:
+ os.killpg(srv.pid, signal.SIGTERM)
+
+ print "FINISHED"