Files
git-hooks/testsuite/bin/run-testcase
Joel Brobecker f18c10b78c stop bypassing the updates.sendmail module during testsuite runs
The goal of this commit is to include the updates.sendmail module
in our testing strategy, in order to make sure that the hooks are
passing email data down to the sendmail program without issues.
This will become particularly important when we switch over to
using Python 3.x, because of the strong distinction between bytes
and strings with newer versions of Python which can cause a lot
problems. Hence the need to use this code during our testing.

The main strategy introduced by this commit to achieve this is
fairly simple: The testsuite framework introduces a new minimal
script to be called in place of the standard sendmail. A new
environment variable called GIT_HOOKS_SENDMAIL is introduced
allowing the testsuite to tell the hooks to use its own (fake)
sendmail instead of the system one. With that in place,
the old code bypassing the use of updates.sendmail can be removed,
thus allowing the testsuite to include it as part of the testing.
The testsuite's (fake) sendmail script was written in a way to
mimick the old bypassing code, so there is no change in output.

Parallel to that, the hooks are enhanced to check that we can
indeed find sendmail, and otherwise return immediately with
an error if not. This way, we avoid emails silently being
dropped due to the missing sendmail.

A couple of testcases are also added to double-check some
specific error situations.

Note that I tried to think of ways to split this patch into
smaller individual parts, but couldn't really find a way to
do so in a meaningful way, while at the same time producing
a commit where the coverage report stays clean (0 lines missed).

TN: U530-006 (transition to Python 3.x)
TN: U924-032 (test for sendmail not found)
TN: U924-034 (test for sendmail override when in testsuite mode)
Change-Id: I74b993592ec6d701347bbca5283a42e037411f1c
2021-09-24 17:41:10 -07:00

120 lines
4.4 KiB
Python

#!/usr/bin/env python
"""Usage: run-test [options] test_dir
Run a git-hooks test located in test_dir.
"""
from __future__ import print_function
from gnatpython.ex import Run
from gnatpython.fileutils import find, cd, mv
from gnatpython.main import Main
from gnatpython.testdriver import TestRunner, add_run_test_options
import os
from os.path import abspath, dirname, isdir
import sys
class TestGitHooks(TestRunner):
def prepare_working_space(self):
"""Prepare the working space.
"""
root_dir = dirname(dirname(dirname(abspath(sys.argv[0]))))
# First, perform the normal preparations (create the working
# space, copy the testcase, etc).
TestRunner.prepare_working_space(self)
src_dir = '%s/src' % self.work_dir
# Next, unpack the git repositories used by this testcase.
current_dir = os.getcwd()
cd(src_dir)
p = Run(['%s/testsuite/bin/unpack-test-repos' % root_dir],
parse_shebang=True)
if p.status != 0:
print(p.out, file=sys.stderr)
sys.exit(p.status)
cd(current_dir)
# And finally, "install" a copy of the git hooks in the bare
# repository. Avoid a copy, and simply create a link, which
# is actually what we do in practice for our real repositories.
# We have to do this here, because we need to know what the
# source directory is (the test script gets run in a temporary
# directory, without any information where the sources are).
git_dir = '%s/bare/repo.git' % src_dir
if isdir('%s/.git' % git_dir):
# This is a non-bare repository (a bit unusual, but
# supported as well). In that case, the git dir is
# that .git/ subdirectory.
git_dir = '%s/.git' % git_dir
os.symlink('%s/hooks' % root_dir, '%s/hooks' % git_dir)
# Also, tell the hooks to use our fake (syslog) logger,
# rather than the real logger. Usually, we do this sort
# of thing in the testcase.Setup method, but we need
# to know the testsuite root dir, which is no longer
# accessible once we reach that point.
os.environ['GIT_HOOKS_LOGGER'] = \
'%s/testsuite/bin/stdout-logger' % root_dir
# Similarly, tell the hooks to use our fake sendmail script,
# rather than the real one (we want those emails to be dumped
# on stdout, rather than actually sent out).
os.environ["GIT_HOOKS_SENDMAIL"] = os.path.join(
root_dir, "testsuite", "bin", "stdout-sendmail-wrapper")
def apply_output_filter(self, str_list):
"""The test is succesful iff the output ends with `OK'.
"""
if str_list and str_list[-1] == 'OK':
return []
return str_list
def write_results(self):
"""Keep coverage data if needed.
"""
TestRunner.write_results(self)
if 'COVERAGE_DIR' in os.environ:
for covf in find(self.work_dir, '.coverage*'):
mv(covf, os.environ['COVERAGE_DIR'])
def main():
"""Run a git-hooks test.
"""
m = Main()
add_run_test_options(m)
m.parse_args()
if not m.args:
sys.exit("Error: 1 argument expected. See -h")
if m.options.restricted_discs is not None:
m.options.restricted_discs = m.options.restricted_discs.split(',')
# Before running the testcase, unset various environment variables
# that the hooks respond to. We do not want the user environment
# to influence the hooks' behavior during testing.
for var_name in ('GIT_HOOKS_CVS_CHECK', 'GIT_HOOKS_DEBUG_LEVEL'):
if var_name in os.environ:
del os.environ[var_name]
t = TestGitHooks(m.args[0],
m.options.discs,
m.options.output_dir,
m.options.tmp,
m.options.enable_cleanup,
m.options.restricted_discs,
len(m.args) > 1 and m.args[1:] or None,
m.options.failed_only)
# Change the name of the testcase script ("test.cmd" or "test.py").
# This is to allow us to implement a step towards moving this testsuite
# to a pytest-based testsuite, where "test.py" isn't a name that pytest
# will consider when looking for testcases.
t.opt_results["CMD"] = "run_test.py"
t.execute()
if __name__ == '__main__':
main()