def wrapped(*args):
			if not manual_session and not use_fixture:
				s, p = new_session(mapgen=mapgen, human_player=human_player, ai_players=ai_players)
			elif use_fixture:
				path = os.path.join(TEST_FIXTURES_DIR, use_fixture + '.sqlite')
				if not os.path.exists(path):
					raise Exception('Savegame {} not found'.format(path))
				s = load_session(path)

			timelimit = Timer(handler)
			timelimit.start(timeout)

			try:
				if use_fixture:
					return func(s, *args)
				elif not manual_session:
					return func(s, p, *args)
				else:
					return func(*args)
			finally:
				try:
					if use_fixture:
						s.end(remove_savegame=False, keep_map=True)
					elif not manual_session:
						s.end()
				except Exception:
					pass
					# An error happened after cleanup after an error.
					# This is ok since cleanup is only defined to work when invariants are in place,
					# but the first error could have violated one.
					# Therefore only use failsafe cleanup:
				finally:
					SPTestSession.cleanup()

				timelimit.stop()
Exemplo n.º 2
0
		def wrapped():
			test_name = '%s.%s' % (func.__module__, func.__name__)
			args = [sys.executable, 'run_uh.py', '--sp-seed', str(RANDOM_SEED), '--gui-test', test_name]
			if use_fixture:
				path = os.path.join(TEST_FIXTURES_DIR, use_fixture + '.sqlite')
				if not os.path.exists(path):
					raise Exception('Savegame %s not found' % path)
				args.extend(['--load-map', path])
			elif use_dev_map:
				args.append('--start-dev-map')

			if ai_players:
				args.extend(['--ai-players', str(ai_players)])

			try:
				# if nose does not capture stdout, then most likely someone wants to
				# use a debugger (he passed -s at the cmdline). In that case, we will
				# redirect stdout/stderr from the gui-test process to the testrunner
				# process.
				sys.stdout.fileno()
				stdout = sys.stdout
				stderr = sys.stderr
				nose_captured = False
			except AttributeError:
				# if nose captures stdout, we can't redirect to sys.stdout, as that was
				# replaced by StringIO. Instead we capture it and return the data at the
				# end.
				stdout = subprocess.PIPE
				stderr = subprocess.PIPE
				nose_captured = True

			# Activate fail-fast, this way the game will stop running when for example the
			# savegame could not be loaded (instead of showing an error popup)
			env = os.environ.copy()
			env['FAIL_FAST'] = '1'
			env['UH_USER_DIR'] = TEST_USER_DIR

			# Start game
			proc = subprocess.Popen(args, stdout=stdout, stderr=stderr, env=env)

			def handler(signum, frame):
				proc.kill()
				raise TestFailed('\n\nTest run exceeded %ds time limit' % timeout)

			timelimit = Timer(handler)
			timelimit.start(timeout)

			stdout, stderr = proc.communicate()
			if proc.returncode != 0:
				if nose_captured:
					if stdout:
						print stdout
					if cleanup_userdir:
						recreate_userdir()
					raise TestFailed('\n\n' + stderr)
				else:
					if cleanup_userdir:
						recreate_userdir()
					raise TestFailed()
Exemplo n.º 3
0
        def wrapped(*args):
            horizons.globals.db = db
            if not manual_session and not use_fixture:
                s, p = new_session(mapgen=mapgen,
                                   human_player=human_player,
                                   ai_players=ai_players)
            elif use_fixture:
                path = os.path.join(TEST_FIXTURES_DIR, use_fixture + '.sqlite')
                if not os.path.exists(path):
                    raise Exception('Savegame %s not found' % path)
                s = load_session(path)

            timelimit = Timer(handler)
            timelimit.start(timeout)

            try:
                if use_fixture:
                    return func(s, *args)
                elif not manual_session:
                    return func(s, p, *args)
                else:
                    return func(*args)
            finally:
                try:
                    if use_fixture:
                        s.end(remove_savegame=False, keep_map=True)
                    elif not manual_session:
                        s.end()
                except:
                    pass
                    # An error happened after cleanup after an error.
                    # This is ok since cleanup is only defined to work when invariants are in place,
                    # but the first error could have violated one.
                    # Therefore only use failsafe cleanup:
                finally:
                    SPTestSession.cleanup()

                timelimit.stop()
Exemplo n.º 4
0
		def wrapped():
			test_name = '%s.%s' % (func.__module__, func.__name__)

			# when running under coverage, enable it for subprocesses too
			if os.environ.get('RUNCOV'):
				executable = ['coverage', 'run']
			else:
				executable = [sys.executable]

			args = executable + ['run_uh.py', '--sp-seed', str(RANDOM_SEED), '--gui-test', test_name]
			if use_fixture:
				path = os.path.join(TEST_FIXTURES_DIR, use_fixture + '.sqlite')
				if not os.path.exists(path):
					raise Exception('Savegame %s not found' % path)
				args.extend(['--load-game', path])
			elif use_dev_map:
				args.append('--start-dev-map')
			elif use_scenario:
				args.extend(['--start-scenario', use_scenario + '.yaml'])

			if ai_players:
				args.extend(['--ai-players', str(ai_players)])

			if additional_cmdline:
				args.extend(additional_cmdline)

			try:
				# if nose does not capture stdout, then most likely someone wants to
				# use a debugger (he passed -s at the cmdline). In that case, we will
				# redirect stdout/stderr from the gui-test process to the testrunner
				# process.
				sys.stdout.fileno()
				stdout = sys.stdout
				stderr = sys.stderr
				nose_captured = False
			except AttributeError:
				# if nose captures stdout, we can't redirect to sys.stdout, as that was
				# replaced by StringIO. Instead we capture it and return the data at the
				# end.
				stdout = subprocess.PIPE
				stderr = subprocess.PIPE
				nose_captured = True

			# Activate fail-fast, this way the game will stop running when for example the
			# savegame could not be loaded (instead of showing an error popup)
			env = os.environ.copy()
			env['FAIL_FAST'] = '1'
			env['UH_USER_DIR'] = _user_dir or TEST_USER_DIR
			if isinstance(env['UH_USER_DIR'], unicode):
				env['UH_USER_DIR'] = env['UH_USER_DIR'].encode('utf-8')

			# Start game
			proc = subprocess.Popen(args, stdout=stdout, stderr=stderr, env=env)

			def handler(signum, frame):
				proc.kill()
				raise TestFailed('\n\nTest run exceeded %ds time limit' % timeout)

			timelimit = Timer(handler)
			timelimit.start(timeout)

			stdout, stderr = proc.communicate()
			if cleanup_userdir:
				recreate_userdir()

			if proc.returncode != 0:
				if nose_captured:
					if stdout:
						print stdout
					if not 'Traceback' in stderr:
						stderr += '\nNo usable error output received, possibly a segfault.'
					raise TestFailed('\n\n' + stderr.decode('ascii', 'ignore'))
				else:
					raise TestFailed()
def pytest_pyfunc_call(pyfuncitem):
	"""
	Tests marked with gui_test will, instead of executing the test function, start a new
	process with the game and run the test function code inside that process.
	"""
	info = pyfuncitem.get_marker('gui_test')
	if not info:
		return

	tmpdir = pyfuncitem._request.getfixturevalue('tmpdir')

	use_fixture = info.kwargs.get('use_fixture', None)
	use_dev_map = info.kwargs.get('use_dev_map', False)
	use_scenario = info.kwargs.get('use_scenario', None)
	ai_players = info.kwargs.get('ai_players', 0)
	additional_cmdline = info.kwargs.get('additional_cmdline', None)
	timeout = info.kwargs.get('timeout', 15 * 60)
	modify_user_dir = info.kwargs.get('_modify_user_dir', lambda v: v)

	test_name = '{}.{}'.format(pyfuncitem.module.__name__, pyfuncitem.name)

	# when running under coverage, enable it for subprocesses too
	if os.environ.get('RUNCOV'):
		executable = ['coverage', 'run']
	else:
		executable = [sys.executable]

	args = executable + ['run_uh.py', '--sp-seed', str(RANDOM_SEED), '--gui-test', test_name]

	if use_fixture:
		path = os.path.join(TEST_FIXTURES_DIR, use_fixture + '.sqlite')
		if not os.path.exists(path):
			raise Exception('Savegame {} not found'.format(path))
		args.extend(['--load-game', path])
	elif use_dev_map:
		args.append('--start-dev-map')
	elif use_scenario:
		args.extend(['--start-scenario', use_scenario + '.yaml'])

	if ai_players:
		args.extend(['--ai-players', str(ai_players)])

	if additional_cmdline:
		args.extend(additional_cmdline)

	user_dir = modify_user_dir(tmpdir.join('user_dir'))

	env = os.environ.copy()
	# Setup temporary user directory for each test
	env['UH_USER_DIR'] = str(user_dir)
	# Activate fail-fast, this way the game will stop running when for example the savegame
	# could not be loaded (instead of showing an error popup)
	env['FAIL_FAST'] = '1'
	# Show additional information (e.g. about threads) when the interpreter crashes
	env['PYTHONFAULTHANDLER'] = '1'

	if pyfuncitem.config.option.capture == 'no':
		# if pytest does not capture stdout, then most likely someone wants to
		# use a debugger (he passed -s at the cmdline). In that case, we will
		# redirect stdout/stderr from the gui-test process to the testrunner
		# process.
		stdout = sys.stdout
		stderr = sys.stderr
		output_captured = False
	else:
		# if pytest captures stdout, we can't redirect to sys.stdout, as that
		# was replaced by a custom object. Instead we capture it and return the
		# data at the end.
		stdout = subprocess.PIPE
		stderr = subprocess.PIPE
		output_captured = True

	# Start game
	proc = subprocess.Popen(args, stdout=stdout, stderr=stderr, env=env)

	def handler(signum, frame):
		proc.kill()
		raise TestFailed('\n\nTest run exceeded {:d}s time limit'.format(timeout))

	timelimit = Timer(handler)
	timelimit.start(timeout)

	stdout, stderr = proc.communicate()

	if proc.returncode != 0:
		if output_captured:
			if stdout:
				print(stdout)
			if b'Traceback' not in stderr:
				stderr += b'\nNo usable error output received, possibly a segfault.'
		raise TestFailed(stderr.decode('ascii'))

	return True
Exemplo n.º 6
0
        def wrapped():
            test_name = '{}.{}'.format(func.__module__, func.__name__)

            # when running under coverage, enable it for subprocesses too
            if os.environ.get('RUNCOV'):
                executable = ['coverage', 'run']
            else:
                executable = [sys.executable]

            args = executable + [
                'run_uh.py', '--sp-seed',
                str(RANDOM_SEED), '--gui-test', test_name
            ]
            if use_fixture:
                path = os.path.join(TEST_FIXTURES_DIR, use_fixture + '.sqlite')
                if not os.path.exists(path):
                    raise Exception('Savegame {} not found'.format(path))
                args.extend(['--load-game', path])
            elif use_dev_map:
                args.append('--start-dev-map')
            elif use_scenario:
                args.extend(['--start-scenario', use_scenario + '.yaml'])

            if ai_players:
                args.extend(['--ai-players', str(ai_players)])

            if additional_cmdline:
                args.extend(additional_cmdline)

            try:
                # if nose does not capture stdout, then most likely someone wants to
                # use a debugger (he passed -s at the cmdline). In that case, we will
                # redirect stdout/stderr from the gui-test process to the testrunner
                # process.

                # nose alters sys.stdout so that fileno is no longer its property
                sys.stdout.fileno()

                stdout = sys.stdout
                stderr = sys.stderr
                nose_captured = False
            except io.UnsupportedOperation:
                # if nose captures stdout, we can't redirect to sys.stdout, as that was
                # replaced by StringIO. Instead we capture it and return the data at the
                # end.
                stdout = subprocess.PIPE
                stderr = subprocess.PIPE
                nose_captured = True

            # Activate fail-fast, this way the game will stop running when for example the
            # savegame could not be loaded (instead of showing an error popup)
            env = os.environ.copy()
            env['FAIL_FAST'] = '1'
            env['UH_USER_DIR'] = _user_dir or TEST_USER_DIR
            env['PYTHONFAULTHANDLER'] = '1'

            # Start game
            proc = subprocess.Popen(args,
                                    stdout=stdout,
                                    stderr=stderr,
                                    env=env)

            def handler(signum, frame):
                proc.kill()
                raise TestFailed(
                    '\n\nTest run exceeded {:d}s time limit'.format(timeout))

            timelimit = Timer(handler)
            timelimit.start(timeout)

            stdout, stderr = proc.communicate()
            if cleanup_userdir:
                recreate_userdir()

            if proc.returncode != 0:
                if nose_captured:
                    if stdout:
                        print(stdout)
                    if b'Traceback' not in stderr:
                        stderr += b'\nNo usable error output received, possibly a segfault.'
                    raise TestFailed('\n\n' + stderr.decode('ascii', 'ignore'))
                else:
                    raise TestFailed()
Exemplo n.º 7
0
def pytest_pyfunc_call(pyfuncitem):
    """
	Tests marked with gui_test will, instead of executing the test function, start a new
	process with the game and run the test function code inside that process.
	"""
    info = pyfuncitem.get_marker('gui_test')
    if not info:
        return

    tmpdir = pyfuncitem._request.getfixturevalue('tmpdir')

    use_fixture = info.kwargs.get('use_fixture', None)
    use_dev_map = info.kwargs.get('use_dev_map', False)
    use_scenario = info.kwargs.get('use_scenario', None)
    ai_players = info.kwargs.get('ai_players', 0)
    additional_cmdline = info.kwargs.get('additional_cmdline', None)
    timeout = info.kwargs.get('timeout', 15 * 60)
    modify_user_dir = info.kwargs.get('_modify_user_dir', lambda v: v)

    test_name = '{}.{}'.format(pyfuncitem.module.__name__, pyfuncitem.name)

    # when running under coverage, enable it for subprocesses too
    if os.environ.get('RUNCOV'):
        executable = ['coverage', 'run']
    else:
        executable = [sys.executable]

    args = executable + [
        'run_uh.py', '--sp-seed',
        str(RANDOM_SEED), '--gui-test', test_name
    ]

    if use_fixture:
        path = os.path.join(TEST_FIXTURES_DIR, use_fixture + '.sqlite')
        if not os.path.exists(path):
            raise Exception('Savegame {} not found'.format(path))
        args.extend(['--load-game', path])
    elif use_dev_map:
        args.append('--start-dev-map')
    elif use_scenario:
        args.extend(['--start-scenario', use_scenario + '.yaml'])

    if ai_players:
        args.extend(['--ai-players', str(ai_players)])

    if additional_cmdline:
        args.extend(additional_cmdline)

    user_dir = modify_user_dir(tmpdir.join('user_dir'))

    env = os.environ.copy()
    # Setup temporary user directory for each test
    env['UH_USER_DIR'] = str(user_dir)
    # Activate fail-fast, this way the game will stop running when for example the savegame
    # could not be loaded (instead of showing an error popup)
    env['FAIL_FAST'] = '1'
    # Show additional information (e.g. about threads) when the interpreter crashes
    env['PYTHONFAULTHANDLER'] = '1'

    if pyfuncitem.config.option.capture == 'no':
        # if pytest does not capture stdout, then most likely someone wants to
        # use a debugger (he passed -s at the cmdline). In that case, we will
        # redirect stdout/stderr from the gui-test process to the testrunner
        # process.
        stdout = sys.stdout
        stderr = sys.stderr
        output_captured = False
    else:
        # if pytest captures stdout, we can't redirect to sys.stdout, as that
        # was replaced by a custom object. Instead we capture it and return the
        # data at the end.
        stdout = subprocess.PIPE
        stderr = subprocess.PIPE
        output_captured = True

    # Start game
    proc = subprocess.Popen(args, stdout=stdout, stderr=stderr, env=env)

    def handler(signum, frame):
        proc.kill()
        raise TestFailed(
            '\n\nTest run exceeded {:d}s time limit'.format(timeout))

    timelimit = Timer(handler)
    timelimit.start(timeout)

    stdout, stderr = proc.communicate()

    if proc.returncode != 0:
        if output_captured:
            if stdout:
                print(stdout)
            if b'Traceback' not in stderr:
                stderr += b'\nNo usable error output received, possibly a segfault.'
        raise TestFailed(stderr.decode('ascii'))

    return True