#!/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 in ('pypy', 'pypy3'):
		prog = ver
	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)
