#!/usr/bin/python
# Copyright 2010-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
#
# Note: We don't want to import portage modules directly because we do things
# like run the testsuite through multiple versions of python.

"""Helper script to run portage unittests against different python versions.

Note: Any additional arguments will be passed down directly to the underlying
unittest runner.  This lets you select specific tests to execute.
"""

from __future__ import print_function

import argparse
import os
import shutil
import subprocess
import sys
import tempfile


# These are the versions we fully support and require to pass tests.
PYTHON_SUPPORTED_VERSIONS = [
	'2.7',
	'3.3',
	'3.4',
]
# The rest are just "nice to have".
PYTHON_NICE_VERSIONS = [
	'pypy',
	'3.5',
]

EPREFIX = os.environ.get('PORTAGE_OVERRIDE_EPREFIX', '/')


class Colors(object):
	"""Simple object holding color constants."""

	_COLORS_YES = ('y', 'yes', 'true')
	_COLORS_NO = ('n', 'no', 'false')

	GOOD = BAD = NORMAL = ''

	def __init__(self, colorize=None):
		if colorize is None:
			nocolors = os.environ.get('NOCOLOR', 'false')
			# Ugh, look away, for here we invert the world!
			if nocolors in self._COLORS_YES:
				colorize = False
			elif nocolors in self._COLORS_NO:
				colorize = True
			else:
				raise ValueError('$NOCOLORS is invalid: %s' % nocolors)
		else:
			if colorize in self._COLORS_YES:
				colorize = True
			elif colorize in self._COLORS_NO:
				colorize = False
			else:
				raise ValueError('--colors is invalid: %s' % colorize)

		if colorize:
			self.GOOD = '\033[1;32m'
			self.BAD = '\033[1;31m'
			self.NORMAL = '\033[0m'


def get_python_executable(ver):
	"""Find the right python executable for |ver|"""
	if ver == 'pypy':
		prog = 'pypy'
	else:
		prog = 'python' + ver
	return os.path.join(EPREFIX, 'usr', 'bin', prog)


def get_parser():
	"""Return a argument parser for this module"""
	epilog = """Examples:
List all the available unittests.
$ %(prog)s --list

Run against specific versions of python.
$ %(prog)s --python-versions '2.7 3.3'

Run just one unittest.
$ %(prog)s pym/portage/tests/xpak/test_decodeint.py
"""
	parser = argparse.ArgumentParser(
		description=__doc__,
		formatter_class=argparse.RawDescriptionHelpFormatter,
		epilog=epilog)
	parser.add_argument('--keep-temp', default=False, action='store_true',
		help='Do not delete the temporary directory when exiting')
	parser.add_argument('--color', type=str, default=None,
		help='Whether to use colorized output (default is auto)')
	parser.add_argument('--python-versions', action='append',
		help='Versions of python to test (default is test available)')
	return parser


def main(argv):
	parser = get_parser()
	opts, args = parser.parse_known_args(argv)
	colors = Colors(colorize=opts.color)

	# Figure out all the versions we want to test.
	if opts.python_versions is None:
		ignore_missing = True
		pyversions = PYTHON_SUPPORTED_VERSIONS + PYTHON_NICE_VERSIONS
	else:
		ignore_missing = False
		pyversions = []
		for ver in opts.python_versions:
			if ver == 'supported':
				pyversions.extend(PYTHON_SUPPORTED_VERSIONS)
			else:
				pyversions.extend(ver.split())

	tempdir = None
	try:
		# Set up a single tempdir for all the tests to use.
		# This way we know the tests won't leak things on us.
		tempdir = tempfile.mkdtemp(prefix='portage.runtests.')
		os.environ['TMPDIR'] = tempdir

		# Actually test those versions now.
		statuses = []
		for ver in pyversions:
			prog = get_python_executable(ver)
			cmd = [prog, '-b', '-Wd', 'pym/portage/tests/runTests.py'] + args
			if os.access(prog, os.X_OK):
				print('%sTesting with Python %s...%s' %
					(colors.GOOD, ver, colors.NORMAL))
				statuses.append(subprocess.call(cmd))
			elif not ignore_missing:
				print('%sCould not find requested Python %s%s' %
					(colors.BAD, ver, colors.NORMAL))
				statuses.append(1)
			print()
	finally:
		if tempdir is not None:
			if opts.keep_temp:
				print('Temporary directory left behind:\n%s' % tempdir)
			else:
				# Nuke our tempdir and anything that might be under it.
				shutil.rmtree(tempdir, True)

	# Then summarize it all.
	print('\nSummary:\n')
	width = 10
	header = '| %-*s | %s' % (width, 'Version', 'Status')
	print('%s\n|%s' % (header, '-' * (len(header) - 1)))
	for ver, status in zip(pyversions, statuses):
		if status:
			color = colors.BAD
			msg = 'FAIL'
		else:
			color = colors.GOOD
			msg = 'PASS'
		print('| %s%-*s%s | %s%s%s' %
			(color, width, ver, colors.NORMAL, color, msg, colors.NORMAL))
	exit(sum(statuses))


if __name__ == '__main__':
	try:
		main(sys.argv[1:])
	except KeyboardInterrupt:
		print('interrupted ...', file=sys.stderr)
		exit(1)
