• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import sys
2import subprocess
3import py
4import cffi.pkgconfig as pkgconfig
5from cffi import PkgConfigError
6
7
8def mock_call(libname, flag):
9    assert libname=="foobarbaz"
10    flags = {
11        "--cflags": "-I/usr/include/python3.6m -DABCD -DCFFI_TEST=1 -O42\n",
12        "--libs": "-L/usr/lib64 -lpython3.6 -shared\n",
13    }
14    return flags[flag]
15
16
17def test_merge_flags():
18    d1 = {"ham": [1, 2, 3], "spam" : ["a", "b", "c"], "foo" : []}
19    d2 = {"spam" : ["spam", "spam", "spam"], "bar" : ["b", "a", "z"]}
20
21    pkgconfig.merge_flags(d1, d2)
22    assert d1 == {
23        "ham": [1, 2, 3],
24        "spam" : ["a", "b", "c", "spam", "spam", "spam"],
25        "bar" : ["b", "a", "z"],
26        "foo" : []}
27
28
29def test_pkgconfig():
30    assert pkgconfig.flags_from_pkgconfig([]) == {}
31
32    saved = pkgconfig.call
33    try:
34        pkgconfig.call = mock_call
35        flags = pkgconfig.flags_from_pkgconfig(["foobarbaz"])
36    finally:
37        pkgconfig.call = saved
38    assert flags == {
39        'include_dirs': ['/usr/include/python3.6m'],
40        'library_dirs': ['/usr/lib64'],
41        'libraries': ['python3.6'],
42        'define_macros': [('ABCD', None), ('CFFI_TEST', '1')],
43        'extra_compile_args': ['-O42'],
44        'extra_link_args': ['-shared']
45    }
46
47class mock_subprocess:
48    PIPE = Ellipsis
49    class Popen:
50        def __init__(self, cmd, stdout, stderr):
51            if mock_subprocess.RESULT is None:
52                raise OSError("oops can't run")
53            assert cmd == ['pkg-config', '--print-errors', '--cflags', 'libfoo']
54        def communicate(self):
55            bout, berr, rc = mock_subprocess.RESULT
56            self.returncode = rc
57            return bout, berr
58
59def test_call():
60    saved = pkgconfig.subprocess
61    try:
62        pkgconfig.subprocess = mock_subprocess
63
64        mock_subprocess.RESULT = None
65        e = py.test.raises(PkgConfigError, pkgconfig.call, "libfoo", "--cflags")
66        assert str(e.value) == "cannot run pkg-config: oops can't run"
67
68        mock_subprocess.RESULT = b"", "Foo error!\n", 1
69        e = py.test.raises(PkgConfigError, pkgconfig.call, "libfoo", "--cflags")
70        assert str(e.value) == "Foo error!"
71
72        mock_subprocess.RESULT = b"abc\\def\n", "", 0
73        e = py.test.raises(PkgConfigError, pkgconfig.call, "libfoo", "--cflags")
74        assert str(e.value).startswith("pkg-config --cflags libfoo returned an "
75                                       "unsupported backslash-escaped output:")
76
77        mock_subprocess.RESULT = b"abc def\n", "", 0
78        result = pkgconfig.call("libfoo", "--cflags")
79        assert result == "abc def\n"
80
81        mock_subprocess.RESULT = b"abc def\n", "", 0
82        result = pkgconfig.call("libfoo", "--cflags")
83        assert result == "abc def\n"
84
85        if sys.version_info >= (3,):
86            mock_subprocess.RESULT = b"\xff\n", "", 0
87            e = py.test.raises(PkgConfigError, pkgconfig.call,
88                               "libfoo", "--cflags", encoding="utf-8")
89            assert str(e.value) == (
90                "pkg-config --cflags libfoo returned bytes that cannot be "
91                "decoded with encoding 'utf-8':\nb'\\xff\\n'")
92
93    finally:
94        pkgconfig.subprocess = saved
95