#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
#
# Univention Admin Modules
#  unit tests: test suite frontend
#
# Copyright 2004-2014 Univention GmbH
#
# http://www.univention.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <http://www.gnu.org/licenses/>.


import os, sys, unittest
from optparse import OptionParser


TEST_SUITE_DIR = '.'

def add_tests(option, opt_str, value, parser, *args):
	parser.values.patterns.extend(args)

def add_all_tests(option, opt_str, value, parser, *args):
	string, = args
	for char in string:
		parser.rargs.append('-%s' % char)

OPTIONS = [
	('-v', '--verbose', {'action': 'store_const',
			     'dest': 'verbose', 'const': 2,
			     'help': 'increase verbosity',}),
	('-c', '--cleanup', {'action': 'store_true',
			     'dest': 'cleanup',
			     'help': 'purge locks (before testing)',}),
	('-m', '--locks', {'action': 'store_true',
			   'dest': 'locks',
			   'help': 'check locks (after testing)',}),
	('-a', '--all', {'action': 'callback',
			 'callback': add_all_tests, 'type': None,
			 'callback_args': ('glmnoprsu',),
			 'help': 'equivalent to "-glmnoprsu"',}),
	('-A', '--almost-all', {'action': 'callback',
				'callback': add_all_tests, 'type': None,
				'callback_args': ('gnoprsu',),
				'help': 'equivalent to "-gnoprsu"',}),
	('-g', '--group', {'action': 'callback',
			   'callback': add_tests, 'type': None,
			   'callback_args': ('Group',),
			   'help': 'run group tests',}),
	('-l', '--listing', {'action': 'callback',
			     'callback': add_tests, 'type': None,
			     'callback_args': ('ModuleList',),
			     'help': 'run listing tests',}),
	('-n', '--network', {'action': 'callback',
			     'callback': add_tests, 'type': None,
			     'callback_args': ('Computer', 'Dhcp', 'Dns',
					       'Network', 'Mail'),
			     'help': 'run computer and network tests',}),
	('-o', '--container', {'action': 'callback',
			       'callback': add_tests, 'type': None,
			       'callback_args': ('Container',),
			       'help': 'run container tests',}),
	('-p', '--policy', {'action': 'callback',
			    'callback': add_tests, 'type': None,
			    'callback_args': ('Policy',),
			    'help': 'run policy tests',}),
	('-r', '--share', {'action': 'callback',
			   'callback': add_tests, 'type': None,
			   'callback_args': ('Share',),
			   'help': 'run share tests',}),
	('-s', '--setting', {'action': 'callback',
			     'callback': add_tests, 'type': None,
			     'callback_args': ('Setting',),
			     'help': 'run setting tests',}),
	('-u', '--user', {'action': 'callback',
			  'callback': add_tests, 'type': None,
			  'callback_args': ('User',),
			  'help': 'run user tests',}),
	('-x', '--extended', {'action': 'store_true',
			      'dest': 'extended',
			      'help': 'run extended tests'}),
	]

def initParser():
	parser = OptionParser()
	parser.set_defaults(verbose=1, cleanup=False, locks=False,
			    extended=False, patterns=[])
	for short, long, kwargs in OPTIONS:
		parser.add_option(short, long, **kwargs)
	return parser

def main():
	parser = initParser()
	opts, args = parser.parse_args()
	default = not args and not opts.patterns and \
		  not opts.cleanup and not opts.locks
	if default:
		parser.print_help()
		return
	runner = unittest.TextTestRunner(stream = sys.stdout,
					 verbosity = opts.verbose)
	suite = unittest.TestSuite()
	if opts.cleanup:
		suite.addTest(cleanup())
	suite.addTest(tests(args, opts.patterns, opts.extended))
	if opts.locks:
		suite.addTest(locks())
	runner.run(suite)

def match(test):
	def __match(pattern):
		p = 'Test' + pattern
		return test.startswith(p)
	return __match

def tests(args, patterns, extended = False):
	suite = unittest.TestSuite()
	tests = (os.path.splitext(file)[0]
		 for file in os.listdir(TEST_SUITE_DIR)
		 if file.startswith('Test')
		 if file.endswith('.py'))
	for test in tests:
		if not filter(match(test), patterns) and not test in args:
			continue
		module = __import__(test)
		if extended and hasattr(module, 'extended'):
			suite.addTest(module.extended())
		else:
			suite.addTest(module.suite())
	return suite

def cleanup():
	import TestLocks
	suite = unittest.TestSuite()
	suite.addTest(TestLocks.LockingTestCase(methodName = 'removeLocks'))
	return suite

def locks():
	import TestLocks
	suite = unittest.TestSuite()
	suite.addTest(TestLocks.LockingTestCase(methodName = 'testLocks'))
	return suite


if __name__ == '__main__':
	main()
