From: Matthew Fernandez Date: Thu, 15 Apr 2021 03:36:52 +0000 (-0700) Subject: consolidate common test suite functionality X-Git-Tag: 2.47.2~58^2~5 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e42b628f79301b18dbae3a5acfff020e0204aa57;p=graphviz consolidate common test suite functionality In future we could grow this gvtest.py to be a more full featured library of common functions we need in the Graphviz test suite. --- diff --git a/rtest/gvtest.py b/rtest/gvtest.py new file mode 100644 index 000000000..391aca17c --- /dev/null +++ b/rtest/gvtest.py @@ -0,0 +1,64 @@ +"""common Graphviz test functionality""" + +import os +from pathlib import Path +import platform +import subprocess +import tempfile +from typing import List, Optional, Tuple + +def compile_c(src: Path, link: List[str] = [], dst: Optional[Path] = None) \ + -> Path: + ''' + compile a C program + ''' + + # if the user did not give us destination, use a temporary path + if dst is None: + _, dst = tempfile.mkstemp('.exe') + + if platform.system() == 'Windows': + # determine which runtime library option we need + rtflag = '-MDd' if os.environ.get('configuration') == 'Debug' else '-MD' + + # construct an invocation of MSVC + args = ['cl', src, '-Fe:', dst, '-nologo', rtflag] + if len(link) > 0: + args += ['-link'] + [f'{l}.lib' for l in link] + + else: + # construct an invocation of the default C compiler + cc = os.environ.get('CC', 'cc') + args = [cc, '-std=c99', src, '-o', dst] + if len(link) > 0: + args += [f'-l{l}' for l in link] + + # compile the program + try: + subprocess.check_call(args) + except subprocess.CalledProcessError: + dst.unlink(missing_ok=True) + raise + + return dst + +def run_c(src: Path, args: [str] = [], input: str = '', link: List[str] = []) \ + -> Tuple[int, str, str]: + ''' + compile and run a C program + ''' + + # create some temporary space to work in + with tempfile.TemporaryDirectory() as tmp: + + # output filename to write our compiled code to + exe = Path(tmp) / 'a.exe' + + # compile the program + compile_c(src, link, exe) + + # run it + p = subprocess.run([exe] + args, input=input, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, universal_newlines=True) + + return p.returncode, p.stdout, p.stderr diff --git a/rtest/test_examples.py b/rtest/test_examples.py index 36374ecd3..5aaa2cf73 100644 --- a/rtest/test_examples.py +++ b/rtest/test_examples.py @@ -6,14 +6,10 @@ import platform import pytest import shutil import subprocess -import tempfile +import sys -def c_compiler(): - '''find the system's C compiler''' - if platform.system() == 'Windows': - return "cl" - else: - return os.environ.get('CC', 'cc') +sys.path.append(os.path.dirname(__file__)) +from gvtest import run_c @pytest.mark.parametrize('src', ['demo.c', 'dot.c', 'example.c', 'neatopack.c', 'simple.c']) @@ -29,40 +25,23 @@ def test_compile_example(src): # construct an absolute path to the example filepath = Path(__file__).parent.resolve() / '..' / 'dot.demo' / src - cc = c_compiler() - - libs = ('cgraph', 'gvc') - - # create some scratch space to work in - with tempfile.TemporaryDirectory() as tmp: - - # compile our test code - exe = Path(tmp) / 'a.exe' - if platform.system() == 'Windows': - debug = os.environ.get('configuration') == 'Debug' - rt_lib_option = '-MDd' if debug else '-MD' - subprocess.check_call([cc, filepath, '-Fe:', exe, '-nologo', - rt_lib_option, '-link'] + [f'{l}.lib' for l in libs]) - else: - subprocess.check_call([cc, '-std=c99', '-o', exe, filepath] - + [f'-l{l}' for l in libs]) - - # FIXME: Remove skip of execution of neatopack.c example when - # https://gitlab.com/graphviz/graphviz/-/issues/1800 has been fixed - if src == 'neatopack.c': - pytest.skip('Executing neatopack gives segmentation fault (#1800)') - - # run the example - args = ['-Kneato'] if src in ['demo.c', 'dot.c'] else []; - - p = subprocess.Popen( - [exe] + args, - stdin=subprocess.PIPE, - universal_newlines=True, - ) - p.communicate(input='graph {a -- b}') - print(f'returncode: {p.returncode} = 0x{p.returncode:08x}') - assert p.returncode == 0 + libs = ['cgraph', 'gvc'] + + # FIXME: Remove skip of execution of neatopack.c example when + # https://gitlab.com/graphviz/graphviz/-/issues/1800 has been fixed + if src == 'neatopack.c': + pytest.skip('Executing neatopack gives segmentation fault (#1800)') + + # run the example + args = ['-Kneato'] if src in ['demo.c', 'dot.c'] else []; + + ret, _, _ = run_c(filepath, args, 'graph {a -- b}', libs) + + print(f'returncode: {ret} = 0x{ret:08x}') + if ret != 0: + print(out) + print(err) + assert ret == 0 @pytest.mark.parametrize('src', ['addrings', 'attr', 'bbox', 'bipart', 'chkedges', 'clustg', 'collapse', 'cycle', 'deghist', 'delmulti', 'depath', diff --git a/rtest/test_regression.py b/rtest/test_regression.py index c51112992..af7ac7daf 100644 --- a/rtest/test_regression.py +++ b/rtest/test_regression.py @@ -6,10 +6,14 @@ import signal import subprocess import os import re +import sys import stat import tempfile from typing import List, Optional, Tuple +sys.path.append(os.path.dirname(__file__)) +from gvtest import run_c + # The terminology used in rtest.py is a little inconsistent. At the # end it reports the total number of tests, the number of "failures" # (crashes) and the number of "changes" (which is the number of tests @@ -39,62 +43,6 @@ def test_regression_failure(): # FIXME: re-enable when all tests pass on all platforms # assert result.returncode == 0 -def compile_c(src: Path, link: List[str] = [], dst: Optional[Path] = None) \ - -> Path: - ''' - compile a C program - ''' - - # if the user did not give us destination, use a temporary path - if dst is None: - _, dst = tempfile.mkstemp('.exe') - - if platform.system() == 'Windows': - # determine which runtime library option we need - rtflag = '-MDd' if os.environ.get('configuration') == 'Debug' else '-MD' - - # construct an invocation of MSVC - args = ['cl', src, '-Fe:', dst, '-nologo', rtflag] - if len(link) > 0: - args += ['-link'] + [f'{l}.lib' for l in link] - - else: - # construct an invocation of the default C compiler - cc = os.environ.get('CC', 'cc') - args = [cc, '-std=c99', src, '-o', dst] - if len(link) > 0: - args += [f'-l{l}' for l in link] - - # compile the program - try: - subprocess.check_call(args) - except subprocess.CalledProcessError: - dst.unlink(missing_ok=True) - raise - - return dst - -def run_c(src: Path, args: [str] = [], input: str = '', link: List[str] = []) \ - -> Tuple[int, str, str]: - ''' - compile and run a C program - ''' - - # create some temporary space to work in - with tempfile.TemporaryDirectory() as tmp: - - # output filename to write our compiled code to - exe = Path(tmp) / 'a.exe' - - # compile the program - compile_c(src, link, exe) - - # run it - p = subprocess.run([exe] + args, input=input, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, universal_newlines=True) - - return p.returncode, p.stdout, p.stderr - def test_131(): ''' PIC back end should produce valid output