Summary
When a regression test that goes through the Python driver layer fails, the actual error (Fortran fatal error, Python traceback, or shared-library load failure) is not shown anywhere the user normally looks. The test simply reports ***Failed with no diagnostic, and the per-case .log file ends mid-run with no error text. This makes these failures very hard to triage.
I hit this with py_wavetank_test1, but the defect is in the shared driver helper and affects every case routed through it (the run*DriverCase family and the C-binding Python tests).
Root cause
_runCase in reg_tests/lib/openfastDrivers.py redirects only stdout to the log file; stderr is never redirected:
def _runCase(executable, inputFile, logFile, stdout, restart=False, ExtraFlags=""):
if logFile is None:
command = f"{executable} {inputFile} {ExtraFlags}"
elif restart:
command = f"{executable} -restart {os.path.splitext(inputFile)[0]} > {logFile}"
else:
command = f"{executable} {inputFile} {ExtraFlags} > {logFile}"
print(command)
return subprocess.call(command, stdout=stdout, shell=True)
Three effects combine to make the failure look silent:
- stdout → log file. The
> {logFile} redirect sends normal progress output into <case>.log, so nothing appears on the console.
- stderr is dropped. There is no
2> / 2>&1, so Python tracebacks, the ctypes "cannot find module / one of its dependencies" DLL-load error, and Fortran fatal errors raised back through the C-binding (e.g. RuntimeError: ... Fatal Error: ...) go to stderr and are written neither to the log file nor merged with stdout.
- ctest hides output by default. Without
--output-on-failure (or -V), ctest captures the streams and only prints ***Failed, so the stderr text that would otherwise reach the console is suppressed too.
Net result: the real error exists but is split — benign stdout into the .log file and the actual error on stderr, which is discarded. The .log for py_wavetank_test1, for example, ended at Running AeroDyn. with no indication of what went wrong.
Steps to reproduce
- Cause any driver-based case to fail for a reason that reports on stderr, e.g. a C-binding fatal error, a missing Python dependency, or a missing/incompatible shared library.
- Run it via ctest:
ctest -R py_wavetank_test1.
- Observe
***Failed with no error message; inspect <build>/.../<case>.log and note it ends mid-run with no error text.
- Run the driver directly capturing all streams (
python <driver>.py *> out.txt, or 2>&1) to finally see the real error.
Expected behavior
The failing command's stderr should be captured into the case .log file (and/or shown by ctest on failure) so the actual error is discoverable without manually re-running the driver.
Proposed fix
Merge stderr into the redirected log in _runCase, e.g.:
elif restart:
command = f"{executable} -restart {os.path.splitext(inputFile)[0]} > {logFile} 2>&1"
else:
command = f"{executable} {inputFile} {ExtraFlags} > {logFile} 2>&1"
(Equivalently, pass stderr=subprocess.STDOUT and write to the log via the file object instead of a shell redirect.) This keeps the console clean while ensuring the .log always contains the error.
Environment
- File:
reg_tests/lib/openfastDrivers.py (_runCase)
Summary
When a regression test that goes through the Python driver layer fails, the actual error (Fortran fatal error, Python traceback, or shared-library load failure) is not shown anywhere the user normally looks. The test simply reports
***Failedwith no diagnostic, and the per-case.logfile ends mid-run with no error text. This makes these failures very hard to triage.I hit this with
py_wavetank_test1, but the defect is in the shared driver helper and affects every case routed through it (therun*DriverCasefamily and the C-binding Python tests).Root cause
_runCaseinreg_tests/lib/openfastDrivers.pyredirects only stdout to the log file; stderr is never redirected:Three effects combine to make the failure look silent:
> {logFile}redirect sends normal progress output into<case>.log, so nothing appears on the console.2>/2>&1, so Python tracebacks, the ctypes "cannot find module / one of its dependencies" DLL-load error, and Fortran fatal errors raised back through the C-binding (e.g.RuntimeError: ... Fatal Error: ...) go to stderr and are written neither to the log file nor merged with stdout.--output-on-failure(or-V), ctest captures the streams and only prints***Failed, so the stderr text that would otherwise reach the console is suppressed too.Net result: the real error exists but is split — benign stdout into the
.logfile and the actual error on stderr, which is discarded. The.logforpy_wavetank_test1, for example, ended atRunning AeroDyn.with no indication of what went wrong.Steps to reproduce
ctest -R py_wavetank_test1.***Failedwith no error message; inspect<build>/.../<case>.logand note it ends mid-run with no error text.python <driver>.py *> out.txt, or2>&1) to finally see the real error.Expected behavior
The failing command's stderr should be captured into the case
.logfile (and/or shown by ctest on failure) so the actual error is discoverable without manually re-running the driver.Proposed fix
Merge stderr into the redirected log in
_runCase, e.g.:(Equivalently, pass
stderr=subprocess.STDOUTand write to the log via the file object instead of a shell redirect.) This keeps the console clean while ensuring the.logalways contains the error.Environment
reg_tests/lib/openfastDrivers.py(_runCase)