Skip to content

Commit

Permalink
Merge branch 'topic/gnatcheck_driver_arbitrary_python_code' into 'mas…
Browse files Browse the repository at this point in the history
…ter'

Allow GNATcheck's testsuite driver to run arbitrary python code

See merge request eng/libadalang/langkit-query-language!52
  • Loading branch information
raph-amiard committed Jun 14, 2023
2 parents e0bda88 + 8e39949 commit ffcb1a5
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 3 deletions.
4 changes: 3 additions & 1 deletion lkql_checker/lalcheck/gnatcheck-compiler.adb
Original file line number Diff line number Diff line change
Expand Up @@ -1485,7 +1485,9 @@ package body Gnatcheck.Compiler is
Args (Num_Args) := new String'("-from=" & Rule_File);

if Debug_Mode then
Put (Worker_Command);
-- For debug purposes, we don't want to put the full path to the
-- worker command, if it is a full path. We just want the base name
Put (Base_Name (Worker_Command));

for J in 1 .. Num_Args loop
Put (" " & Args (J).all);
Expand Down
42 changes: 40 additions & 2 deletions testsuite/support/gnatcheck_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ class GnatcheckDriver(BaseDriver):
In this case, the test keys specified at the top level are taken as
default, and can be overriden in specific subtests.
Test env keys are provided for the user to execute arbitrary Python code as
part of the test/subtests. The ``global_python`` key can be used to alter
the python execution environment to store data/functions that need to be
called by test-specific python hooks described below.
This driver also supports performance testing.
Test arguments:
Expand All @@ -55,6 +60,8 @@ class GnatcheckDriver(BaseDriver):
- ``perf``: Enable and configure the performance testing. Perf arguments:
- ``default``: Time measuring repetition number as an integer
- ``profile-time``: Enable the time profiling or not as a boolean
- ``pre_python``/``post_python``: Python code to be executed
before/after the test
.. NOTE:: In practice, the above allows several different ways to express
the same test, which is not ideal. It was necessary to transition
Expand All @@ -77,15 +84,41 @@ def run(self):
self.gnatcheck_worker_exe
)

globs, locs = {}, {}
global_python = self.test_env.get("global_python", None)
if global_python:
exec(global_python, globs, locs)

def capture_exec_python(code: str) -> None:
"""
Execute the python code, and capture it's output. Add it to the
test's output.
"""
from io import StringIO
from contextlib import redirect_stdout
f = StringIO()
cwd = os.getcwd()
os.chdir(self.test_env["working_dir"])
with redirect_stdout(f):
exec(code, globs, locs)
self.output += f.getvalue()
os.chdir(cwd)

def run_one_test(test_data):
output_format = test_data.get('format', 'full')
assert output_format in GnatcheckDriver.output_formats

brief = output_format == 'brief'

exe = GnatcheckDriver.modes[test_data.get('mode', 'gnatcheck')]
args = [exe, '-q']

pre_python = test_data.get('pre_python', None)
post_python = test_data.get('post_python', None)

# If python code to be executed pre running gnatcheck was passed
# for this test, run it and capture its output
if pre_python:
capture_exec_python(pre_python)

# Use the test's project, if any
if test_data.get('project', None):
args += ['-P', test_data['project']]
Expand Down Expand Up @@ -151,6 +184,11 @@ def run_one_test(test_data):
if (not brief and p.status not in [0, 1]) or (brief and p.status != 0):
self.output += ">>>program returned status code {}\n".format(p.status)

# If python code to be executed post running gnatcheck was passed
# for this test, run it and capture its output
if post_python:
capture_exec_python(post_python)

tests = self.test_env.get("tests")
if tests:
for i, test in enumerate(tests):
Expand Down

0 comments on commit ffcb1a5

Please sign in to comment.